Browse Source

HPCC-18934 Fix Windows build broken by libbase58 use of C99 extensions

Also add cppunit test for libbase58 b58enc().

Signed-off-by: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
Anthony Fishbeck 7 years ago
parent
commit
c3ae4d4efe
3 changed files with 117 additions and 3 deletions
  1. 11 3
      system/libbase58/base58.c
  2. 2 0
      testing/unittests/CMakeLists.txt
  3. 104 0
      testing/unittests/unittests.cpp

+ 11 - 3
system/libbase58/base58.c

@@ -9,6 +9,7 @@
 #include <arpa/inet.h>
 #else
 #include <winsock2.h>
+typedef SSIZE_T ssize_t;
 #endif
 
 #include <stdbool.h>
@@ -16,6 +17,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <sys/types.h>
+#include <memory>
 
 #include "libbase58.h"
 
@@ -38,7 +40,7 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz)
     const unsigned char *b58u = (const unsigned char *)b58;
     unsigned char *binu = (unsigned char *)bin;
     size_t outisz = (binsz + 3) / 4;
-    uint32_t outi[outisz];
+    uint32_t *outi = (uint32_t*)alloca(outisz * sizeof(uint32_t));
     uint64_t t;
     uint32_t c;
     size_t i, j;
@@ -145,6 +147,12 @@ static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdef
 bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
 {
     const uint8_t *bin = (const uint8_t *) data;
+    if (!binsz && *b58sz) //empty not much to do
+    {
+        *b58=0;
+        *b58sz=1;
+        return true;
+    }
     int carry;
     ssize_t i, j, high, zcount = 0;
     size_t size;
@@ -153,7 +161,7 @@ bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
         ++zcount;
 
     size = (binsz - zcount) * 138 / 100 + 1;
-    uint8_t buf[size];
+    uint8_t *buf = (uint8_t*)alloca(size);
     memset(buf, 0, size);
 
     for (i = zcount, high = size - 1; i < binsz; ++i, high = j)
@@ -186,7 +194,7 @@ bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
 
 bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz)
 {
-    uint8_t buf[1 + datasz + 0x20];
+    uint8_t *buf = (uint8_t*)alloca(1 + datasz + 0x20);
     uint8_t *hash = &buf[1 + datasz];
 
     buf[0] = ver;

+ 2 - 0
testing/unittests/CMakeLists.txt

@@ -38,6 +38,7 @@ include_directories (
          ./../../system/include
          ./../../system/jlib
          ./../../system/mp
+         ./../../system/libbase58
          ./../../common/remote
          ./../../dali/base
          ./../../system/security/shared
@@ -54,6 +55,7 @@ target_link_libraries ( unittests
          remote
          dalibase
          deftype
+         libbase58
          ${CPPUNIT_LIBRARIES}
     )
 

+ 104 - 0
testing/unittests/unittests.cpp

@@ -22,6 +22,7 @@
 #include "jfile.hpp"
 #include "deftype.hpp"
 #include "rmtfile.hpp"
+#include "libbase58.h"
 
 /*
  * This is the main unittest driver for HPCC. From here,
@@ -569,5 +570,108 @@ class StringBufferTest : public CppUnit::TestFixture
 CPPUNIT_TEST_SUITE_REGISTRATION( StringBufferTest );
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( StringBufferTest, "StringBufferTest" );
 
+StringBuffer &mbToBase58(StringBuffer &s, const MemoryBuffer &data)
+{
+    size_t b58Length = data.length() * 2 + 1;
+
+    ASSERT(b58enc(s.clear().reserve(b58Length), &b58Length, data.toByteArray(), data.length()));
+
+    s.setLength(b58Length);
+    return s;
+}
+
+StringBuffer &base64ToBase58(StringBuffer &s, const char *b64)
+{
+    MemoryBuffer mb;
+    JBASE64_Decode(b64, mb);
+    return mbToBase58(s, mb);
+}
+
+StringBuffer &textToBase58(StringBuffer &s, const char *text)
+{
+    MemoryBuffer mb;
+    mb.append((size_t)strlen(text), text);
+    return mbToBase58(s, mb);
+}
+
+MemoryBuffer &base58ToMb(MemoryBuffer &data, const char *b58)
+{
+    size_t len = strlen(b58);
+    size_t offset = len;
+    b58tobin(data.clear().reserveTruncate(len), &len, b58, 0);
+    offset -= len;
+    if (offset) //if we ever start using b58tobin we should fix this weird behavior
+    {
+        MemoryBuffer weird;
+        weird.append(len, data.toByteArray()+offset);
+        data.swapWith(weird);
+    }
+    return data;
+}
+
+StringBuffer &base58ToBase64(StringBuffer &s, const char *b58)
+{
+    MemoryBuffer mb;
+    base58ToMb(mb, b58);
+    JBASE64_Encode(mb.toByteArray(), mb.length(), s.clear());
+    return s;
+}
+
+StringBuffer &base58ToText(StringBuffer &s, const char *b58)
+{
+    MemoryBuffer mb;
+    base58ToMb(mb, b58);
+    return s.clear().append(mb.length(), mb.toByteArray());
+}
+
+class Base58Test : public CppUnit::TestFixture
+{
+    CPPUNIT_TEST_SUITE( Base58Test  );
+        CPPUNIT_TEST(testEncodeDecode);
+    CPPUNIT_TEST_SUITE_END();
+
+    void doTestEncodeDecodeText(const char *text, const char *b58)
+    {
+        StringBuffer s;
+        ASSERT(streq(textToBase58(s, text), b58));
+        ASSERT(streq(base58ToText(s, b58), text));
+    }
+    void doTestEncodeDecodeBase64(const char *b64, const char *b58)
+    {
+        StringBuffer s;
+        ASSERT(streq(base64ToBase58(s, b64), b58));
+        ASSERT(streq(base58ToBase64(s, b58), b64));
+    }
+    void testEncodeDecode()
+    {
+        StringBuffer s;
+
+        //short string
+        doTestEncodeDecodeText("1", "r");
+
+        //text string
+        doTestEncodeDecodeText("Fifty-eight is the sum of the first seven prime numbers.", "2ubdTkzo5vaWL4FKQGro88zp8v6Q5EftVBq2fbZsWCDRzQxGDb1heKFsMReJNhsRsK6TfvrgqVeRB");
+
+        //hex 005A1FC5DD9E6F03819FCA94A2D89669469667F9A074655946
+        doTestEncodeDecodeBase64("AFofxd2ebwOBn8qUotiWaUaWZ/mgdGVZRg==", "19DXstMaV43WpYg4ceREiiTv2UntmoiA9j");
+
+        //hex FEEFAEF022FA
+        doTestEncodeDecodeBase64("/u+u8CL6", "3Bx9Y4pUR");
+
+        //hex FFFEEFAEF022FA
+        doTestEncodeDecodeBase64("//7vrvAi+g==", "AhfV5sjWb3");
+
+        //This input causes the loop iteration counter to go negative
+        //hex 00CEF022FA
+        doTestEncodeDecodeBase64("AM7wIvo=", "16Ho7Hs");
+
+        //empty input
+        MemoryBuffer mb;
+        ASSERT(streq(mbToBase58(s, mb), ""));
+}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION( Base58Test );
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( Base58Test, "Base58Test" );
 
 #endif // _USE_CPPUNIT