mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 08:41:03 +00:00
Fix a vulnerability in the timsort algorithm where an algorithmic problem caused an
invariant to no longer hold for certain inputs, potentially leading to a read beyond an array boundary (result in a segfault under our implementation). See http://www.envisage-project.eu/proving-android-java-and-python-sorting-algorithm-is-broken-and-how-to-fix-it/ for an in-depth explanation of the problem. Also: ‘Yeah!’ for formal verification! git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@38391 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
0d742c1913
commit
e5a29578ad
2 changed files with 28 additions and 23 deletions
|
@ -1,3 +1,10 @@
|
|||
2015-03-10 Niels Grewe <niels.grewe@halbordnung.de>
|
||||
|
||||
* Source/GSTimSort.m: Fix a DoS vulnerability discovered in the
|
||||
Timsort algorithm. For information about the problem please refer to
|
||||
http://www.envisage-project.eu/proving-android-java-and-python-sorting
|
||||
-algorithm-is-broken-and-how-to-fix-it/
|
||||
|
||||
2015-03-08 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSFileHandle.m: ([-sslHandshakeEstablished:outgoing:])
|
||||
|
|
|
@ -615,38 +615,36 @@ descriptorOrComparator: (id)descriptorOrComparator
|
|||
NSDebugMLLog(@"GSTimSort", @"Pushing run: %@", NSStringFromRange(r));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the invariant enabling the algorithm holds for the stack.
|
||||
*
|
||||
* see: http://www.envisage-project.eu/proving-android-java-and-python-sorting-algorithm-is-broken-and-how-to-fix-it/#sec3
|
||||
*/
|
||||
- (void) suggestMerge
|
||||
{
|
||||
while (stackSize > 1)
|
||||
{
|
||||
NSInteger n = stackSize -2;
|
||||
|
||||
if (n > 0)
|
||||
if ( (n >= 1
|
||||
&& runStack[n-1].length <= (runStack[n].length
|
||||
+ runStack[n+1].length)
|
||||
)
|
||||
|| (n >= 2
|
||||
&& runStack[n-2].length <= (runStack[n].length
|
||||
+ runStack[n-1].length)
|
||||
)
|
||||
)
|
||||
{
|
||||
NSUInteger topLen = runStack[n+1].length;
|
||||
NSUInteger midLen = runStack[n].length;
|
||||
NSUInteger botLen = runStack[n-1].length;
|
||||
if (botLen <= (midLen + topLen))
|
||||
if (runStack[n-1].length < runStack[n+1].length)
|
||||
{
|
||||
if (botLen < topLen)
|
||||
{
|
||||
n--;
|
||||
}
|
||||
GS_TIMSORT_MERGE_AT_INDEX(self, n);
|
||||
}
|
||||
else if (midLen <= topLen)
|
||||
{
|
||||
GS_TIMSORT_MERGE_AT_INDEX(self, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (runStack[n].length > runStack[n+1].length)
|
||||
{
|
||||
break; //invariant reached
|
||||
}
|
||||
GS_TIMSORT_MERGE_AT_INDEX(self, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue