From e5a29578ad6f8c21b7da4e5d6ce02f73223bb996 Mon Sep 17 00:00:00 2001 From: thebeing Date: Tue, 10 Mar 2015 11:43:03 +0000 Subject: [PATCH] =?UTF-8?q?Fix=20a=20vulnerability=20in=20the=20timsort=20?= =?UTF-8?q?algorithm=20where=20an=20algorithmic=20problem=20caused=20an=20?= =?UTF-8?q?invariant=20to=20no=20longer=20hold=20for=20certain=20inputs,?= =?UTF-8?q?=20potentially=20leading=20to=20a=20read=20beyond=20an=20array?= =?UTF-8?q?=20boundary=20(result=20in=20a=20segfault=20under=20our=20imple?= =?UTF-8?q?mentation).=20See=20http://www.envisage-project.eu/proving-andr?= =?UTF-8?q?oid-java-and-python-sorting-algorithm-is-broken-and-how-to-fix-?= =?UTF-8?q?it/=20for=20an=20in-depth=20explanation=20of=20the=20problem.?= =?UTF-8?q?=20Also:=20=E2=80=98Yeah!=E2=80=99=20for=20formal=20verificatio?= =?UTF-8?q?n!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@38391 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 7 +++++++ Source/GSTimSort.m | 44 +++++++++++++++++++++----------------------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 97a87b34e..7b278b224 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2015-03-10 Niels Grewe + + * 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 * Source/NSFileHandle.m: ([-sslHandshakeEstablished:outgoing:]) diff --git a/Source/GSTimSort.m b/Source/GSTimSort.m index 836fb90b3..30f251b07 100644 --- a/Source/GSTimSort.m +++ b/Source/GSTimSort.m @@ -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); } }