From 91abee564144def1dd802350c9dcc98f6331dcc4 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 3 Jan 2025 13:25:06 +0100 Subject: [PATCH] Issue 193 and issue 194: Always use heapsort instead of quicksort. The quicksort implementation behaves badly when presented with non-deterministic comparison functions. The heapsort is more robust and has fewer edge cases to worry about in the face of an adversarial comparison function. --- jsarray.c | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) diff --git a/jsarray.c b/jsarray.c index 83c3a43..962d59f 100644 --- a/jsarray.c +++ b/jsarray.c @@ -346,8 +346,6 @@ static void Ap_sort_swap(js_State *J, int idx_a, int idx_b) } } -#if JS_HEAPSORT - /* A bottom-up/bouncing heapsort implementation */ static int Ap_sort_leaf(js_State *J, int i, int end) @@ -390,46 +388,6 @@ static void Ap_sort_heapsort(js_State *J, int n) } } -#else - -static int Ap_sort_quicksort_partition(js_State *J, int a, int b) -{ - int pivot = (a + b) >> 1; - while (a <= b) { - while (Ap_sort_cmp(J, a, pivot) < 0) - ++a; - while (Ap_sort_cmp(J, b, pivot) > 0) - --b; - if (a <= b) { - Ap_sort_swap(J, a, b); - ++a; - --b; - } - } - return a; -} - -static void Ap_sort_quicksort(js_State *J, int a, int b) -{ - int i, j, m; - - /* insertion sort small fragments */ - if (b - a < 8) { - for (i = a+1; i < b; ++i) - for (j = i; j > a && Ap_sort_cmp(J, j-1, j) > 0; --j) - Ap_sort_swap(J, j-1, j); - return; - } - - m = Ap_sort_quicksort_partition(J, a, b); - if (a < m - 1) - Ap_sort_quicksort(J, a, m - 1); - if (m < b) - Ap_sort_quicksort(J, m, b); -} - -#endif - static void Ap_sort(js_State *J) { int len; @@ -446,12 +404,7 @@ static void Ap_sort(js_State *J) if (len >= INT_MAX) js_rangeerror(J, "array is too large to sort"); - -#if JS_HEAPSORT Ap_sort_heapsort(J, len); -#else - Ap_sort_quicksort(J, 0, len - 1); -#endif js_copy(J, 0); }