[glib/glib-2-52] gbase64: Fix base-64 stepped encoding with small chunks
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/glib-2-52] gbase64: Fix base-64 stepped encoding with small chunks
- Date: Sat, 8 Apr 2017 05:48:49 +0000 (UTC)
commit 5596bfb71e0a0d11ed8fb314c09f363edfd3d9b9
Author: Philip Withnall <withnall endlessm com>
Date: Fri Mar 17 11:30:47 2017 +0000
gbase64: Fix base-64 stepped encoding with small chunks
If encoding with small chunks such that the call to
g_base64_encode_close() has to deal with 0 < x < 24 bits of remaining
state, the encoding code would not correctly use zeroes to pad out the
state — it would use left-over state from an earlier iteration in the
encoding process.
This resulted in invalid base-64 encodings.
Add a unit test for incremental encoding using different sized chunks
too.
Thanks to Rainier Perske for reporting and analysing the bug.
https://bugzilla.gnome.org/show_bug.cgi?id=780066
Signed-off-by: Philip Withnall <withnall endlessm com>
glib/gbase64.c | 1 +
glib/tests/base64.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 0 deletions(-)
---
diff --git a/glib/gbase64.c b/glib/gbase64.c
index 7bca5ab..4dc1518 100644
--- a/glib/gbase64.c
+++ b/glib/gbase64.c
@@ -222,6 +222,7 @@ g_base64_encode_close (gboolean break_lines,
goto skip;
case 1:
outptr[2] = '=';
+ c2 = 0; /* saved state here is not relevant */
skip:
outptr [0] = base64_alphabet [ c1 >> 2 ];
outptr [1] = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 )];
diff --git a/glib/tests/base64.c b/glib/tests/base64.c
index ffb00d5..86875a2 100644
--- a/glib/tests/base64.c
+++ b/glib/tests/base64.c
@@ -236,6 +236,58 @@ test_base64_encode (void)
}
}
+/* Test that incremental and all-in-one encoding of strings of a length which
+ * is not a multiple of 3 bytes behave the same, as the state carried over
+ * between g_base64_encode_step() calls varies depending on how the input is
+ * split up. This is like the test_base64_decode_smallblock() test, but for
+ * encoding. */
+static void
+test_base64_encode_incremental_small_block (gconstpointer block_size_p)
+{
+ gsize i;
+ struct MyRawData myraw;
+
+ g_test_bug ("780066");
+
+ generate_databuffer_for_base64 (&myraw);
+
+ for (i = 0; ok_100_encode_strs[i] != NULL; i++)
+ {
+ const guint block_size = GPOINTER_TO_UINT (block_size_p);
+ gchar *encoded_complete = NULL;
+ gchar encoded_stepped[1024];
+ gint state = 0, save = 0;
+ gsize len_written, len_read, len_to_read, input_length;
+
+ input_length = i + 1;
+
+ /* Do it all at once. */
+ encoded_complete = g_base64_encode (myraw.data, input_length);
+
+ /* Split the data up so some number of bits remain after each step. */
+ for (len_written = 0, len_read = 0; len_read < input_length; len_read += len_to_read)
+ {
+ len_to_read = MIN (block_size, input_length - len_read);
+ len_written += g_base64_encode_step (myraw.data + len_read, len_to_read,
+ FALSE,
+ encoded_stepped + len_written,
+ &state, &save);
+ }
+
+ len_written += g_base64_encode_close (FALSE, encoded_stepped + len_written,
+ &state, &save);
+ g_assert_cmpuint (len_written, <, G_N_ELEMENTS (encoded_stepped));
+
+ /* Nul-terminate to make string comparison easier. */
+ encoded_stepped[len_written] = '\0';
+
+ /* Compare results. They should be the same. */
+ g_assert_cmpstr (encoded_complete, ==, ok_100_encode_strs[i]);
+ g_assert_cmpstr (encoded_stepped, ==, encoded_complete);
+
+ g_free (encoded_complete);
+ }
+}
static void
decode_and_compare (const gchar *datap,
@@ -361,6 +413,7 @@ main (int argc, char *argv[])
gint i;
g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("https://bugzilla.gnome.org/browse.cgi?product=");
for (i = 0; i < DATA_SIZE; i++)
data[i] = (guchar)i;
@@ -370,6 +423,11 @@ main (int argc, char *argv[])
g_test_add_data_func ("/base64/full/3", GINT_TO_POINTER (2), test_full);
g_test_add_data_func ("/base64/full/4", GINT_TO_POINTER (3), test_full);
+ g_test_add_data_func ("/base64/encode/incremental/small-block/1", GINT_TO_POINTER (1),
test_base64_encode_incremental_small_block);
+ g_test_add_data_func ("/base64/encode/incremental/small-block/2", GINT_TO_POINTER (2),
test_base64_encode_incremental_small_block);
+ g_test_add_data_func ("/base64/encode/incremental/small-block/3", GINT_TO_POINTER (3),
test_base64_encode_incremental_small_block);
+ g_test_add_data_func ("/base64/encode/incremental/small-block/4", GINT_TO_POINTER (4),
test_base64_encode_incremental_small_block);
+
g_test_add_data_func ("/base64/incremental/nobreak/1", GINT_TO_POINTER (DATA_SIZE),
test_incremental_nobreak);
g_test_add_data_func ("/base64/incremental/break/1", GINT_TO_POINTER (DATA_SIZE), test_incremental_break);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]