ossl_bsearch(): New generic internal binary search utility function
authorRichard Levitte <levitte@openssl.org>
Wed, 8 May 2019 08:40:20 +0000 (10:40 +0200)
committerRichard Levitte <levitte@openssl.org>
Wed, 8 May 2019 14:17:16 +0000 (16:17 +0200)
OBJ_bsearch_ and OBJ_bsearch_ex_ are generic functions that don't
really belong with the OBJ API, but should rather be generic utility
functions.  The ending underscore indicates that they are considered
internal, even though they are declared publicly.

Since crypto/stack/stack.c uses OBJ_bsearch_ex_, the stack API ends up
depending on the OBJ API, which is unnecessary, and carries along
other dependencies.

Therefor, a generic internal function is created, ossl_bsearch().
This removes the unecessary dependencies.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8899)

crypto/bsearch.c [new file with mode: 0644]
crypto/build.info
crypto/objects/obj_dat.c
crypto/stack/stack.c
include/internal/cryptlib.h

diff --git a/crypto/bsearch.c b/crypto/bsearch.c
new file mode 100644 (file)
index 0000000..f812c4f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stddef.h>
+#include "internal/cryptlib.h"
+
+const void *ossl_bsearch(const void *key, const void *base, int num,
+                         int size, int (*cmp) (const void *, const void *),
+                         int flags)
+{
+    const char *base_ = base;
+    int l, h, i = 0, c = 0;
+    const char *p = NULL;
+
+    if (num == 0)
+        return NULL;
+    l = 0;
+    h = num;
+    while (l < h) {
+        i = (l + h) / 2;
+        p = &(base_[i * size]);
+        c = (*cmp) (key, p);
+        if (c < 0)
+            h = i;
+        else if (c > 0)
+            l = i + 1;
+        else
+            break;
+    }
+    if (c != 0 && !(flags & OSSL_BSEARCH_VALUE_ON_NOMATCH))
+        p = NULL;
+    else if (c == 0 && (flags & OSSL_BSEARCH_FIRST_VALUE_ON_MATCH)) {
+        while (i > 0 && (*cmp) (key, &(base_[(i - 1) * size])) == 0)
+            i--;
+        p = &(base_[i * size]);
+    }
+    return p;
+}
index 30dcf8c91eb8997066f9520ed205dfa08327b1cc..fa99d61bd646baf27e2aa39b6e1ee80cd714cd8f 100644 (file)
@@ -18,12 +18,12 @@ SOURCE[../libcrypto]=\
         ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c ctype.c \
         threads_pthread.c threads_win.c threads_none.c getenv.c \
         o_init.c o_fips.c mem_sec.c init.c context.c sparse_array.c \
-        trace.c provider.c params.c \
+        trace.c provider.c params.c bsearch.c \
         {- $target{cpuid_asm_src} -} {- $target{uplink_aux_src} -}
 
 # FIPS module
 SOURCE[../providers/fips]=\
-        cryptlib.c mem.c mem_clr.c params.c
+        cryptlib.c mem.c mem_clr.c params.c bsearch.c
 
 
 DEPEND[cversion.o]=buildinf.h
index f374d19fc7eab5a16e15a4f67e654743f71801af..ec9e13133724b0041d91aa843fd31c00b5dc4a70 100644 (file)
@@ -585,52 +585,32 @@ const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
     return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
 }
 
-const void *OBJ_bsearch_ex_(const void *key, const void *base_, int num,
+const void *OBJ_bsearch_ex_(const void *key, const void *base, int num,
                             int size,
                             int (*cmp) (const void *, const void *),
                             int flags)
 {
-    const char *base = base_;
-    int l, h, i = 0, c = 0;
-    const char *p = NULL;
+    const char *p = ossl_bsearch(key, base, num, size, cmp, flags);
 
-    if (num == 0)
-        return NULL;
-    l = 0;
-    h = num;
-    while (l < h) {
-        i = (l + h) / 2;
-        p = &(base[i * size]);
-        c = (*cmp) (key, p);
-        if (c < 0)
-            h = i;
-        else if (c > 0)
-            l = i + 1;
-        else
-            break;
-    }
 #ifdef CHARSET_EBCDIC
     /*
      * THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I
      * don't have perl (yet), we revert to a *LINEAR* search when the object
      * wasn't found in the binary search.
      */
-    if (c != 0) {
+    if (p == NULL) {
+        const char *base_ = base;
+        int l, h, i = 0, c = 0;
+
         for (i = 0; i < num; ++i) {
-            p = &(base[i * size]);
+            p = &(base_[i * size]);
             c = (*cmp) (key, p);
-            if (c == 0 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
+            if (c == 0
+                || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
                 return p;
         }
     }
 #endif
-    if (c != 0 && !(flags & OBJ_BSEARCH_VALUE_ON_NOMATCH))
-        p = NULL;
-    else if (c == 0 && (flags & OBJ_BSEARCH_FIRST_VALUE_ON_MATCH)) {
-        while (i > 0 && (*cmp) (key, &(base[(i - 1) * size])) == 0)
-            i--;
-        p = &(base[i * size]);
-    }
     return p;
 }
 
index 2f0ed64232a052622b665218a975493fcea1f7fc..450a4e1a0e6e952a878dd34e9714d3a85aebb502 100644 (file)
@@ -11,7 +11,6 @@
 #include "internal/cryptlib.h"
 #include "internal/numbers.h"
 #include <openssl/stack.h>
-#include <openssl/objects.h>
 #include <errno.h>
 #include <openssl/e_os2.h>      /* For ossl_inline */
 
@@ -307,20 +306,20 @@ static int internal_find(OPENSSL_STACK *st, const void *data,
     }
     if (data == NULL)
         return -1;
-    r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp,
-                        ret_val_options);
+    r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp,
+                     ret_val_options);
 
     return r == NULL ? -1 : (int)((const void **)r - st->data);
 }
 
 int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
 {
-    return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH);
+    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH);
 }
 
 int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
 {
-    return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH);
+    return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH);
 }
 
 int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
index df23f578e379662de754f07488a700c2df7b70f9..46b5d344a4c2d1f51d9d4db46de75df9e61800bd 100644 (file)
@@ -174,4 +174,15 @@ int crypto_get_ex_new_index_ex(OPENSSL_CTX *ctx, int class_index,
                                CRYPTO_EX_dup *dup_func,
                                CRYPTO_EX_free *free_func);
 int crypto_free_ex_index_ex(OPENSSL_CTX *ctx, int class_index, int idx);
+
+/* Function for simple binary search */
+
+/* Flags */
+# define OSSL_BSEARCH_VALUE_ON_NOMATCH            0x01
+# define OSSL_BSEARCH_FIRST_VALUE_ON_MATCH        0x02
+
+const void *ossl_bsearch(const void *key, const void *base, int num,
+                         int size, int (*cmp) (const void *, const void *),
+                         int flags);
+
 #endif