]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
unit1302: expand the base64 encode/decode tests
authorDaniel Stenberg <daniel@haxx.se>
Mon, 23 Jun 2025 20:53:30 +0000 (22:53 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 24 Jun 2025 05:55:16 +0000 (07:55 +0200)
Closes #17726

tests/unit/unit1302.c

index f161cf29e3a6f9eb209272ca24c670bee7ef78e9..1b1f4b44ba7101baa4920bceb4058a28c6f0ecf6 100644 (file)
 #include <curlx/base64.h>
 #include "memdebug.h" /* LAST include file */
 
+struct etest {
+  const char *input;
+  size_t ilen;
+  const char *output;
+  size_t olen;
+};
+
 static CURLcode test_unit1302(char *arg)
 {
   UNITTEST_BEGIN_SIMPLE
-
-  char *output;
-  unsigned char *decoded;
-  size_t size = 0;
-  unsigned char anychar = 'x';
   CURLcode rc;
-
-  rc = curlx_base64_encode("i", 1, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 4, "size should be 4");
-  verify_memory(output, "aQ==", 4);
-  Curl_safefree(output);
-
-  rc = curlx_base64_encode("ii", 2, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 4, "size should be 4");
-  verify_memory(output, "aWk=", 4);
-  Curl_safefree(output);
-
-  rc = curlx_base64_encode("iii", 3, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 4, "size should be 4");
-  verify_memory(output, "aWlp", 4);
-  Curl_safefree(output);
-
-  rc = curlx_base64_encode("iiii", 4, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 8, "size should be 8");
-  verify_memory(output, "aWlpaQ==", 8);
-  Curl_safefree(output);
-
-  rc = curlx_base64_encode("\xff\x01\xfe\x02", 4, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 8, "size should be 8");
-  verify_memory(output, "/wH+Ag==", 8);
-  Curl_safefree(output);
-
-  rc = curlx_base64url_encode("\xff\x01\xfe\x02", 4, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 6, "size should be 6");
-  verify_memory(output, "_wH-Ag", 6);
-  Curl_safefree(output);
-
-  rc = curlx_base64url_encode("iiii", 4, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 6, "size should be 6");
-  verify_memory(output, "aWlpaQ", 6);
-  Curl_safefree(output);
-
-  /* 0 length makes it do strlen() */
-  rc = curlx_base64_encode("iiii", 0, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 8, "size should be 8");
-  verify_memory(output, "aWlpaQ==", 8);
-  Curl_safefree(output);
-
-  rc = curlx_base64_encode("", 0, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 0, "size should be 0");
-  fail_unless(output && !output[0], "output should be a zero-length string");
-  Curl_safefree(output);
-
-  rc = curlx_base64url_encode("", 0, &output, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 0, "size should be 0");
-  fail_unless(output && !output[0], "output should be a zero-length string");
-  Curl_safefree(output);
-
-  rc = curlx_base64_decode("aWlpaQ==", &decoded, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 4, "size should be 4");
-  verify_memory(decoded, "iiii", 4);
-  Curl_safefree(decoded);
-
-  rc = curlx_base64_decode("aWlp", &decoded, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 3, "size should be 3");
-  verify_memory(decoded, "iii", 3);
-  Curl_safefree(decoded);
-
-  rc = curlx_base64_decode("aWk=", &decoded, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 2, "size should be 2");
-  verify_memory(decoded, "ii", 2);
-  Curl_safefree(decoded);
-
-  rc = curlx_base64_decode("aQ==", &decoded, &size);
-  fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-  fail_unless(size == 1, "size should be 1");
-  verify_memory(decoded, "i", 2);
-  Curl_safefree(decoded);
-
-  /* This is illegal input as the data is too short */
-  size = 1; /* not zero */
-  decoded = &anychar; /* not NULL */
-  rc = curlx_base64_decode("aQ", &decoded, &size);
-  fail_unless(rc == CURLE_BAD_CONTENT_ENCODING,
-              "return code should be CURLE_BAD_CONTENT_ENCODING");
-  fail_unless(size == 0, "size should be 0");
-  fail_if(decoded, "returned pointer should be NULL");
-
-  /* This is illegal input as it contains three padding characters */
-  size = 1; /* not zero */
-  decoded = &anychar; /* not NULL */
-  rc = curlx_base64_decode("a===", &decoded, &size);
-  fail_unless(rc == CURLE_BAD_CONTENT_ENCODING,
-              "return code should be CURLE_BAD_CONTENT_ENCODING");
-  fail_unless(size == 0, "size should be 0");
-  fail_if(decoded, "returned pointer should be NULL");
-
-  /* This is illegal input as it contains a padding character mid input */
-  size = 1; /* not zero */
-  decoded = &anychar; /* not NULL */
-  rc = curlx_base64_decode("a=Q=", &decoded, &size);
-  fail_unless(rc == CURLE_BAD_CONTENT_ENCODING,
-              "return code should be CURLE_BAD_CONTENT_ENCODING");
-  fail_unless(size == 0, "size should be 0");
-  fail_if(decoded, "returned pointer should be NULL");
-
-  /* This is also illegal input as it contains a padding character mid input */
-  size = 1; /* not zero */
-  decoded = &anychar; /* not NULL */
-  rc = curlx_base64_decode("aWlpa=Q=", &decoded, &size);
-  fail_unless(rc == CURLE_BAD_CONTENT_ENCODING,
-              "return code should be CURLE_BAD_CONTENT_ENCODING");
-  fail_unless(size == 0, "size should be 0");
-  fail_if(decoded, "returned pointer should be NULL");
-
-  /* This is garbage input as it contains an illegal base64 character */
-  size = 1; /* not zero */
-  decoded = &anychar; /* not NULL */
-  rc = curlx_base64_decode("a\x1f==", &decoded, &size);
-  fail_unless(rc == CURLE_BAD_CONTENT_ENCODING,
-              "return code should be CURLE_BAD_CONTENT_ENCODING");
-  fail_unless(size == 0, "size should be 0");
-  fail_if(decoded, "returned pointer should be NULL");
+  unsigned int i;
+
+  /* common base64 encoding */
+  struct etest encode[] = {
+    {"iiiiii", 1, "aQ==", 4 },
+    {"iiiiii", 2, "aWk=", 4 },
+    {"iiiiii", 3, "aWlp", 4 },
+    {"iiiiii", 4, "aWlpaQ==", 8 },
+    {"iiiiii", 5, "aWlpaWk=", 8 },
+    {"iiiiii", 6, "aWlpaWlp", 8 },
+    {"iiiiiii", 7, "aWlpaWlpaQ==", 12 },
+    {"iiiiiiii", 8, "aWlpaWlpaWk=", 12 },
+    {"iiiiiiiii", 9, "aWlpaWlpaWlp", 12 },
+    {"iiiiiiiiii", 10, "aWlpaWlpaWlpaQ==", 16 },
+    {"iiiiiiiiiii", 11, "aWlpaWlpaWlpaWk=", 16 },
+    {"iiiiiiiiiiii", 12, "aWlpaWlpaWlpaWlp", 16 },
+    {"\xff\x01\xfe\x02", 4, "/wH+Ag==", 8 },
+    {"\xff\xff\xff\xff", 4, "/////w==", 8 },
+    {"\x00\x00\x00\x00", 4, "AAAAAA==", 8 },
+    {"\x00\x00\x00\x00", 1, "AA==", 4 },
+  };
+
+  /* base64 URL encoding */
+  struct etest url[] = {
+    {"", 0, "", 0 },
+    {"iiiiiiiiiii", 1, "aQ", 2 },
+    {"iiiiiiiiiii", 2, "aWk", 3 },
+    {"iiiiiiiiiii", 3, "aWlp", 4 },
+    {"iiiiiiiiiii", 4, "aWlpaQ", 6 },
+    {"iiiiiiiiiii", 5, "aWlpaWk", 7 },
+    {"iiiiiiiiiii", 6, "aWlpaWlp", 8 },
+    {"iiiiiiiiiii", 7, "aWlpaWlpaQ", 10 },
+    {"iiiiiiiiiii", 8, "aWlpaWlpaWk", 11 },
+    {"iiiiiiiiiii", 9, "aWlpaWlpaWlp", 12 },
+    {"iiiiiiiiiii", 10, "aWlpaWlpaWlpaQ", 14 },
+    {"iiiiiiiiiii", 11, "aWlpaWlpaWlpaWk", 15 },
+    {"iiiiiiiiiiii", 12, "aWlpaWlpaWlpaWlp", 16 },
+    {"\xff\x01\xfe\x02", 4, "_wH-Ag", 6 },
+    {"\xff\xff\xff\xff", 4, "_____w", 6 },
+    {"\xff\x00\xff\x00", 4, "_wD_AA", 6 },
+    {"\x00\xff\x00\xff", 4, "AP8A_w", 6 },
+    {"\x00\x00\x00\x00", 4, "AAAAAA", 6 },
+    {"\x00", 1, "AA", 2 },
+    {"\x01", 1, "AQ", 2 },
+    {"\x02", 1, "Ag", 2 },
+    {"\x03", 1, "Aw", 2 },
+    {"\x04", 1, "BA", 2 },
+    {"\x05", 1, "BQ", 2 },
+    {"\x06", 1, "Bg", 2 },
+    {"\x07", 1, "Bw", 2 },
+    {"\x08", 1, "CA", 2 },
+    {"\x09", 1, "CQ", 2 },
+    {"\x0a", 1, "Cg", 2 },
+    {"\x0b", 1, "Cw", 2 },
+    {"\x0c", 1, "DA", 2 },
+    {"\x0d", 1, "DQ", 2 },
+    {"\x0e", 1, "Dg", 2 },
+    {"\x0f", 1, "Dw", 2 },
+    {"\x10", 1, "EA", 2 },
+  };
+
+  /* bad decode inputs */
+  struct etest badecode[] = {
+    {"", 0, "", 0 }, /* no dats means error */
+    {"", 0, "a", 1 }, /* data is too short */
+    {"", 0, "aQ", 2 }, /* data is too short */
+    {"", 0, "aQ=", 3 }, /* data is too short */
+    {"", 0, "====", 1 }, /* data is only padding characters */
+    {"", 0, "====", 2 }, /* data is only padding characters */
+    {"", 0, "====", 3 }, /* data is only padding characters */
+    {"", 0, "====", 4 }, /* data is only padding characters */
+    {"", 0, "a===", 4 }, /* contains three padding characters */
+    {"", 0, "a=Q=", 4 }, /* contains a padding character mid input */
+    {"", 0, "aWlpa=Q=", 8 }, /* contains a padding character mid input */
+    {"", 0, "a\x1f==", 4 }, /* contains illegal base64 character */
+    {"", 0, "abcd ", 5 }, /* contains illegal base64 character */
+    {"", 0, "abcd  ", 6 }, /* contains illegal base64 character */
+    {"", 0, " abcd", 5 }, /* contains illegal base64 character */
+    {"", 0, "_abcd", 5 }, /* contains illegal base64 character */
+    {"", 0, "abcd-", 5 }, /* contains illegal base64 character */
+    {"", 0, "abcd_", 5 }, /* contains illegal base64 character */
+    {"", 0, "aWlpaWlpaQ==-", 17}, /* bad character after padding */
+    {"", 0, "aWlpaWlpaQ==_", 17}, /* bad character after padding */
+    {"", 0, "aWlpaWlpaQ== ", 17}, /* bad character after padding */
+    {"", 0, "aWlpaWlpaQ=", 15} /* unaligned size, missing a padding char */
+  };
+
+  for(i = 0 ; i < CURL_ARRAYSIZE(encode); i++) {
+    struct etest *e = &encode[i];
+    char *out;
+    unsigned char *decoded;
+    size_t olen;
+    size_t dlen;
+
+    /* first encode */
+    rc = curlx_base64_encode(e->input, e->ilen, &out, &olen);
+    abort_unless(rc == CURLE_OK, "return code should be CURLE_OK");
+    abort_unless(olen == e->olen, "wrong output size");
+    if(memcmp(out, e->output, e->olen)) {
+      fprintf(stderr, "Test %u encoded badly\n", i);
+      unitfail++;
+    }
+    Curl_safefree(out);
+
+    /* then verify decode */
+    rc = curlx_base64_decode(e->output, &decoded, &dlen);
+    if(rc != CURLE_OK) {
+      fprintf(stderr, "Test %u URL decode returned %d\n", i, (int)rc);
+      unitfail++;
+    }
+    if(dlen != e->ilen) {
+      fprintf(stderr, "Test %u URL decode output length %d instead of %d\n",
+              i, (int)dlen, (int)e->ilen);
+      unitfail++;
+    }
+    if(memcmp(decoded, e->input, dlen)) {
+      fprintf(stderr, "Test %u URL decoded badly. Got '%s', expected '%s'\n",
+              i, decoded, e->input);
+      unitfail++;
+    }
+
+    Curl_safefree(decoded);
+  }
+
+  for(i = 0 ; i < CURL_ARRAYSIZE(url); i++) {
+    struct etest *e = &url[i];
+    char *out;
+    size_t olen;
+    rc = curlx_base64url_encode(e->input, e->ilen, &out, &olen);
+    abort_unless(rc == CURLE_OK, "return code should be CURLE_OK");
+    if(olen != e->olen) {
+      fprintf(stderr, "Test %u URL encoded output length %d instead of %d\n",
+              i, (int)olen, (int)e->olen);
+    }
+    if(memcmp(out, e->output, e->olen)) {
+      fprintf(stderr, "Test %u URL encoded badly. Got '%s', expected '%s'\n",
+              i, out, e->output);
+      unitfail++;
+    }
+    Curl_safefree(out);
+  }
+
+  for(i = 0 ; i < CURL_ARRAYSIZE(badecode); i++) {
+    struct etest *e = &badecode[i];
+    unsigned char *decoded;
+    size_t dlen;
+
+    /* then verify decode with illegal inputs */
+    rc = curlx_base64_decode(e->output, &decoded, &dlen);
+    if(rc != CURLE_BAD_CONTENT_ENCODING) {
+      fprintf(stderr, "Test %u URL bad decoded badly. "
+              "Returned '%d', expected '%d'\n",
+              i, (int)rc, CURLE_BAD_CONTENT_ENCODING);
+      unitfail++;
+    }
+  }
 
   UNITTEST_END_SIMPLE
 }