Merge branch '1698-base64-encoding' into 'master'

Resolve "g_base64_encode(NULL, 0) causes critical warnings"

Closes #1698

See merge request GNOME/glib!695
This commit is contained in:
Sebastian Dröge 2019-02-27 11:42:04 +00:00
commit cdcb6c2cf1
2 changed files with 93 additions and 10 deletions

View File

@ -100,12 +100,12 @@ g_base64_encode_step (const guchar *in,
char *outptr;
const guchar *inptr;
g_return_val_if_fail (in != NULL, 0);
g_return_val_if_fail (in != NULL || len == 0, 0);
g_return_val_if_fail (out != NULL, 0);
g_return_val_if_fail (state != NULL, 0);
g_return_val_if_fail (save != NULL, 0);
if (len <= 0)
if (len == 0)
return 0;
inptr = in;
@ -160,7 +160,8 @@ g_base64_encode_step (const guchar *in,
*state = already;
}
if (len>0)
g_assert (len == 0 || len == 1 || len == 2);
{
char *saveout;
@ -244,7 +245,7 @@ g_base64_encode_close (gboolean break_lines,
/**
* g_base64_encode:
* @data: (array length=len) (element-type guint8): the binary data to encode
* @data: (array length=len) (element-type guint8) (nullable): the binary data to encode
* @len: the length of @data
*
* Encode a sequence of binary data into its Base-64 stringified
@ -268,9 +269,7 @@ g_base64_encode (const guchar *data,
/* We can use a smaller limit here, since we know the saved state is 0,
+1 is needed for trailing \0, also check for unlikely integer overflow */
if (len >= ((G_MAXSIZE - 1) / 4 - 1) * 3)
g_error("%s: input too large for Base64 encoding (%"G_GSIZE_FORMAT" chars)",
G_STRLOC, len);
g_return_val_if_fail (len < ((G_MAXSIZE - 1) / 4 - 1) * 3, NULL);
out = g_malloc ((len / 3 + 1) * 4 + 1);
@ -336,12 +335,12 @@ g_base64_decode_step (const gchar *in,
unsigned int v;
int i;
g_return_val_if_fail (in != NULL, 0);
g_return_val_if_fail (in != NULL || len == 0, 0);
g_return_val_if_fail (out != NULL, 0);
g_return_val_if_fail (state != NULL, 0);
g_return_val_if_fail (save != NULL, 0);
if (len <= 0)
if (len == 0)
return 0;
inend = (const guchar *)in+len;
@ -392,7 +391,7 @@ g_base64_decode_step (const gchar *in,
/**
* g_base64_decode:
* @text: zero-terminated string with base64 text to decode
* @text: (not nullable): zero-terminated string with base64 text to decode
* @out_len: (out): The length of the decoded data is written here
*
* Decode a sequence of Base-64 encoded text into binary data. Note

View File

@ -406,6 +406,85 @@ test_base64_decode_smallblock (gconstpointer blocksize_p)
}
}
/* Test that calling g_base64_encode (NULL, 0) returns correct output. This is
* as per the first test vector in RFC 4648 §10.
* https://tools.ietf.org/html/rfc4648#section-10 */
static void
test_base64_encode_empty (void)
{
gchar *encoded = NULL;
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1698");
encoded = g_base64_encode (NULL, 0);
g_assert_cmpstr (encoded, ==, "");
g_free (encoded);
encoded = g_base64_encode ((const guchar *) "", 0);
g_assert_cmpstr (encoded, ==, "");
g_free (encoded);
}
/* Test that calling g_base64_decode ("", *) returns correct output. This is
* as per the first test vector in RFC 4648 §10. Note that calling
* g_base64_decode (NULL, *) is not allowed.
* https://tools.ietf.org/html/rfc4648#section-10 */
static void
test_base64_decode_empty (void)
{
guchar *decoded = NULL;
gsize decoded_len;
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1698");
decoded = g_base64_decode ("", &decoded_len);
g_assert_cmpstr ((gchar *) decoded, ==, "");
g_assert_cmpuint (decoded_len, ==, 0);
g_free (decoded);
}
/* Check all the RFC 4648 test vectors for base 64 encoding from §10.
* https://tools.ietf.org/html/rfc4648#section-10 */
static void
test_base64_encode_decode_rfc4648 (void)
{
const struct
{
const gchar *decoded; /* technically this should be a byte array, but all the test vectors are ASCII strings */
const gchar *encoded;
}
vectors[] =
{
{ "", "" },
{ "f", "Zg==" },
{ "fo", "Zm8=" },
{ "foo", "Zm9v" },
{ "foob", "Zm9vYg==" },
{ "fooba", "Zm9vYmE=" },
{ "foobar", "Zm9vYmFy" },
};
gsize i;
for (i = 0; i < G_N_ELEMENTS (vectors); i++)
{
gchar *encoded = NULL;
guchar *decoded = NULL;
gsize expected_decoded_len = strlen (vectors[i].decoded);
gsize decoded_len;
g_test_message ("Vector %" G_GSIZE_FORMAT ": %s", i, vectors[i].decoded);
encoded = g_base64_encode ((const guchar *) vectors[i].decoded, expected_decoded_len);
g_assert_cmpstr (encoded, ==, vectors[i].encoded);
decoded = g_base64_decode (encoded, &decoded_len);
g_assert_cmpstr ((gchar *) decoded, ==, vectors[i].decoded);
g_assert_cmpuint (decoded_len, ==, expected_decoded_len);
g_free (encoded);
g_free (decoded);
}
}
int
main (int argc, char *argv[])
@ -455,5 +534,10 @@ main (int argc, char *argv[])
g_test_add_data_func ("/base64/incremental/smallblock/4", GINT_TO_POINTER(4),
test_base64_decode_smallblock);
g_test_add_func ("/base64/encode/empty", test_base64_encode_empty);
g_test_add_func ("/base64/decode/empty", test_base64_decode_empty);
g_test_add_func ("/base64/encode-decode/rfc4648", test_base64_encode_decode_rfc4648);
return g_test_run ();
}