[1/2] msvcrt: qsort_s implementation and tests (try 3)

Vincas Miliūnas vincas.miliunas at gmail.com
Wed Nov 3 15:23:53 CDT 2010


qsort_s implementation and tests for bug #24925.

Moved the code from msvcr80 to msvcrt.
Added parameter validation for implementation and tests.

---
 dlls/msvcr100/msvcr100.spec |    2 +-
 dlls/msvcr80/msvcr80.spec   |    2 +-
 dlls/msvcr90/msvcr90.spec   |    2 +-
 dlls/msvcrt/misc.c          |   86 +++++++++++++++++++++++++++++++++++++++++++
 dlls/msvcrt/msvcrt.spec     |    2 +-
 5 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index e451db9..8e02195 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -1550,7 +1550,7 @@
 @ cdecl putwc(long ptr) msvcrt.putwc
 @ cdecl putwchar(long) msvcrt.putwchar
 @ cdecl qsort(ptr long long ptr) msvcrt.qsort
-@ stub qsort_s
+@ cdecl qsort_s(ptr long long ptr ptr) msvcrt.qsort_s
 @ cdecl raise(long) msvcrt.raise
 @ cdecl rand() msvcrt.rand
 @ cdecl rand_s(ptr) msvcrt.rand_s
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 1734c72..0234b4d 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -1404,7 +1404,7 @@
 @ cdecl putwc(long ptr) msvcrt.putwc
 @ cdecl putwchar(long) msvcrt.putwchar
 @ cdecl qsort(ptr long long ptr) msvcrt.qsort
-@ stub qsort_s
+@ cdecl qsort_s(ptr long long ptr ptr) msvcrt.qsort_s
 @ cdecl raise(long) msvcrt.raise
 @ cdecl rand() msvcrt.rand
 @ cdecl rand_s(ptr) msvcrt.rand_s
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index f188329..d766a41 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -1388,7 +1388,7 @@
 @ cdecl putwc(long ptr) msvcrt.putwc
 @ cdecl putwchar(long) msvcrt.putwchar
 @ cdecl qsort(ptr long long ptr) msvcrt.qsort
-@ stub qsort_s
+@ cdecl qsort_s(ptr long long ptr ptr) msvcrt.qsort_s
 @ cdecl raise(long) msvcrt.raise
 @ cdecl rand() msvcrt.rand
 @ cdecl rand_s(ptr) msvcrt.rand_s
diff --git a/dlls/msvcrt/misc.c b/dlls/msvcrt/misc.c
index c044d63..5286185 100644
--- a/dlls/msvcrt/misc.c
+++ b/dlls/msvcrt/misc.c
@@ -29,6 +29,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 
+typedef int (CDECL *_QSORT_S_COMPARE_FN)(void *, const void *, const void *);
 
 /*********************************************************************
  *        _beep (MSVCRT.@)
@@ -186,3 +187,88 @@ void CDECL _chkesp(void)
 # endif  /* __GNUC__ */
 
 #endif  /* __i386__ */
+
+/*********************************************************************
+ * Helper function for MSVCRT_qsort_s.
+ *
+ * Based on http://github.com/git/git/blob/master/compat/qsort.c
+ *
+ */
+void msort_with_tmp(void *b, size_t n, size_t s, _QSORT_S_COMPARE_FN cmp,
+    void *context, char *t)
+{
+    char *tmp;
+    char *b1, *b2;
+    size_t n1, n2;
+
+    if (n <= 1)
+        return;
+
+    n1 = n / 2;
+    n2 = n - n1;
+    b1 = b;
+    b2 = (char *)b + (n1 * s);
+
+    msort_with_tmp(b1, n1, s, cmp, context, t);
+    msort_with_tmp(b2, n2, s, cmp, context, t);
+
+    tmp = t;
+
+    while (n1 > 0 && n2 > 0) {
+        if (b1 == b2 || cmp(context, b1, b2) <= 0) {
+            memcpy(tmp, b1, s);
+            tmp += s;
+            b1 += s;
+            --n1;
+        } else {
+            memcpy(tmp, b2, s);
+            tmp += s;
+            b2 += s;
+            --n2;
+        }
+    }
+    if (n1 > 0)
+        memcpy(tmp, b1, n1 * s);
+    memcpy(b, t, (n - n2) * s);
+}
+
+/*********************************************************************
+ * qsort_s (MSVCRT.@)
+ *
+ * Based on http://github.com/git/git/blob/master/compat/qsort.c
+ *
+ */
+void CDECL MSVCRT_qsort_s(void *b, size_t n, size_t s,
+    _QSORT_S_COMPARE_FN cmp, void *context)
+{
+    const size_t size = n * s;
+    char buf[1024];
+
+    if (!MSVCRT_CHECK_PMT(b != NULL || (b == NULL && n == 0)) || !MSVCRT_CHECK_PMT(s > 0) ||
+        !MSVCRT_CHECK_PMT(cmp != NULL))
+    {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+    
+    if (b == NULL && n == 0) {
+        return;
+    }
+
+    if (size < sizeof(buf))
+    {
+        /* The temporary array fits on the small on-stack buffer. */
+        msort_with_tmp(b, n, s, cmp, context, buf);
+    } else {
+        /* It's somewhat large, so malloc it.  */
+        char *tmp = (char *) malloc(size);
+        if (!tmp)
+        {
+            *MSVCRT__errno() = MSVCRT_ENOMEM;
+            return;
+        }
+        msort_with_tmp(b, n, s, cmp, context, tmp);
+        free(tmp);
+    }
+}
+
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index a667ada..8442c02 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -1344,7 +1344,7 @@
 @ cdecl putwc(long ptr) MSVCRT_fputwc
 @ cdecl putwchar(long) _fputwchar
 @ cdecl qsort(ptr long long ptr) ntdll.qsort
-# stub qsort_s
+@ cdecl qsort_s(ptr long long ptr ptr) MSVCRT_qsort_s
 @ cdecl raise(long) MSVCRT_raise
 @ cdecl rand() MSVCRT_rand
 @ cdecl rand_s(ptr) MSVCRT_rand_s
-- 
1.7.2.3




More information about the wine-patches mailing list