diff options
author | Marc-André Lureau <marcandre.lureau@gmail.com> | 2023-01-04 15:33:07 +0000 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@gmail.com> | 2023-01-04 15:33:07 +0000 |
commit | 3b6942d7ff3bb0b1671f894aba2010b384809fc4 (patch) | |
tree | 3327b253420b7b16ace30303c9b344e9f6f671d1 | |
parent | 274e0bba51d007f8b5b4c09b26ec50b5999efdfb (diff) | |
parent | 690377dfae69eeea54826fbd2c7156e2147d2cee (diff) | |
download | gcab-3b6942d7ff3bb0b1671f894aba2010b384809fc4.tar.gz |
Merge branch 'wip/hughsie/allowed_compression' into 'master'
Allow specifying the allowed compression formats at runtime
See merge request GNOME/gcab!15
-rw-r--r-- | libgcab/gcab-cabinet.c | 48 | ||||
-rw-r--r-- | libgcab/gcab-cabinet.h | 2 | ||||
-rw-r--r-- | libgcab/libgcab.syms | 4 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | tests/gcab-self-test.c | 42 |
5 files changed, 97 insertions, 1 deletions
diff --git a/libgcab/gcab-cabinet.c b/libgcab/gcab-cabinet.c index 10087e9..0bcbf00 100644 --- a/libgcab/gcab-cabinet.c +++ b/libgcab/gcab-cabinet.c @@ -44,6 +44,7 @@ struct _GCabCabinet { cheader_t *cheader; GByteArray *signature; GInputStream *stream; + guint8 allowed_compression; }; enum { @@ -64,6 +65,7 @@ gcab_error_quark (void) static void gcab_cabinet_init (GCabCabinet *self) { + self->allowed_compression = GCAB_COMPRESSION_MASK; self->folders = g_ptr_array_new_with_free_func (g_object_unref); } @@ -416,6 +418,41 @@ gcab_cabinet_new (void) return g_object_new (GCAB_TYPE_CABINET, NULL); } +static gboolean +gcab_cabinet_is_compression_allowed(GCabCabinet *self, GCabCompression compression) +{ + /* for the fuzzing self tests */ + if (self->allowed_compression == 0) + return TRUE; + return (self->allowed_compression & (1ull << compression)) > 0; +} + +/** + * gcab_cabinet_add_allowed_compression: + * @cabinet: a #GCabCabinet + * @compression: a #GCabCompression kind, e.g. %GCAB_COMPRESSION_MSZIP + * + * Adds a compression kind to the allow-list. By default, GCab will use all decompression support + * compiled in at build time. Once this function has been called only specific compression kinds + * will be used in functions like gcab_cabinet_load(). + * + * Since: 1.6 + **/ +void +gcab_cabinet_add_allowed_compression (GCabCabinet *self, GCabCompression compression) +{ + g_return_if_fail (GCAB_IS_CABINET (self)); + g_return_if_fail (compression < GCAB_COMPRESSION_MASK); + + /* clear all */ + if (self->allowed_compression == GCAB_COMPRESSION_MASK) + self->allowed_compression = 0x0; + + /* enable this */ + if (g_getenv ("GCAB_SKIP_COMPRESSION_CHECK") == NULL) + self->allowed_compression |= 1ull << compression; +} + /** * gcab_cabinet_load: * @cabinet: a #GCabCabinet @@ -460,9 +497,20 @@ gcab_cabinet_load (GCabCabinet *self, for (guint i = 0; i < cheader->nfolders; i++) { g_autoptr(cfolder_t) cfolder = g_new0 (cfolder_t, 1); g_autoptr(GByteArray) blob = NULL; + if (!cfolder_read (cfolder, cheader->res_folder, in, cancellable, error)) return FALSE; + /* only allow some compression types at runtime */ + if (!gcab_cabinet_is_compression_allowed (self, cfolder->typecomp)) { + g_set_error (error, + GCAB_ERROR, + GCAB_ERROR_NOT_SUPPORTED, + "compression kind 0x%x not allowed", + cfolder->typecomp); + return FALSE; + } + /* steal this inelegantly */ if (cfolder->reserved != NULL) { blob = g_byte_array_new_take (cfolder->reserved, cheader->res_folder); diff --git a/libgcab/gcab-cabinet.h b/libgcab/gcab-cabinet.h index 36d13b1..229cb0e 100644 --- a/libgcab/gcab-cabinet.h +++ b/libgcab/gcab-cabinet.h @@ -64,6 +64,8 @@ typedef enum GCabError } GCabError; GCabCabinet * gcab_cabinet_new (void); +void gcab_cabinet_add_allowed_compression (GCabCabinet *self, + GCabCompression compression); gboolean gcab_cabinet_load (GCabCabinet *cabinet, GInputStream *stream, GCancellable *cancellable, diff --git a/libgcab/libgcab.syms b/libgcab/libgcab.syms index 7c27ffd..df9d5ab 100644 --- a/libgcab/libgcab.syms +++ b/libgcab/libgcab.syms @@ -60,3 +60,7 @@ LIBGCAB1_1.4 { LIBGCAB1_1.5 { gcab_file_set_bytes; } LIBGCAB1_1.4; + +LIBGCAB1_1.6 { + gcab_cabinet_add_allowed_compression; +} LIBGCAB1_1.5; diff --git a/meson.build b/meson.build index 5eba715..d8ef2de 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('gcab', 'c', - version : '1.5', + version : '1.6', license : 'LGPL-2.1+', meson_version : '>=0.50.0', default_options : ['warning_level=2', 'c_std=c99'], diff --git a/tests/gcab-self-test.c b/tests/gcab-self-test.c index 66f1edb..bc487b3 100644 --- a/tests/gcab-self-test.c +++ b/tests/gcab-self-test.c @@ -420,6 +420,7 @@ gcab_test_cabinet_error_cves_func (void) "CVE-2015-4471.cab", NULL }; (void)g_setenv ("GCAB_SKIP_CHECKSUM", "1", TRUE); + (void)g_setenv ("GCAB_SKIP_COMPRESSION_CHECK", "1", TRUE); for (guint i = 0; tests[i] != NULL; i++) { gboolean ret; g_autofree gchar *fn = NULL; @@ -438,6 +439,7 @@ gcab_test_cabinet_error_cves_func (void) g_assert_no_error (error); g_assert (in != NULL); cabinet = gcab_cabinet_new (); + gcab_cabinet_add_allowed_compression (cabinet, GCAB_COMPRESSION_NONE); ret = gcab_cabinet_load (cabinet, in, NULL, &error); g_assert_no_error (error); g_assert (ret); @@ -447,6 +449,44 @@ gcab_test_cabinet_error_cves_func (void) g_assert (!ret); } g_unsetenv ("GCAB_SKIP_CHECKSUM"); + g_unsetenv ("GCAB_SKIP_COMPRESSION_CHECK"); +} + +static void +gcab_test_cabinet_allowed_compression_func (void) +{ + gboolean ret; + g_autofree gchar *fn = NULL; + g_autoptr(GCabCabinet) cabinet = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GFile) file = NULL; + g_autoptr(GInputStream) in = NULL; + + /* load file */ + fn = gcab_test_get_filename ("test-mszip.cab"); + g_assert (fn != NULL); + file = g_file_new_for_path (fn); + in = G_INPUT_STREAM (g_file_read (file, NULL, &error)); + g_assert_no_error (error); + g_assert (in != NULL); + + /* add the one it is not for a failure */ + cabinet = gcab_cabinet_new (); + gcab_cabinet_add_allowed_compression (cabinet, GCAB_COMPRESSION_LZX); + ret = gcab_cabinet_load (cabinet, in, NULL, &error); + g_assert_error (error, GCAB_ERROR, GCAB_ERROR_NOT_SUPPORTED); + g_assert_false (ret); + g_clear_error (&error); + g_clear_object (&in); + + /* add the correct one and try again */ + in = G_INPUT_STREAM (g_file_read (file, NULL, &error)); + g_assert_no_error (error); + g_assert (in != NULL); + gcab_cabinet_add_allowed_compression (cabinet, GCAB_COMPRESSION_MSZIP); + ret = gcab_cabinet_load (cabinet, in, NULL, &error); + g_assert_no_error (error); + g_assert (ret); } static void @@ -468,6 +508,7 @@ gcab_test_cabinet_signature_func (void) g_assert_no_error (error); g_assert (in != NULL); cabinet = gcab_cabinet_new (); + gcab_cabinet_add_allowed_compression (cabinet, GCAB_COMPRESSION_NONE); ret = gcab_cabinet_load (cabinet, in, NULL, &error); g_assert_no_error (error); g_assert (ret); @@ -587,5 +628,6 @@ main (int argc, char **argv) g_test_add_func ("/GCab/cabinet{write}", gcab_test_cabinet_write_func); g_test_add_func ("/GCab/cabinet{blob}", gcab_test_cabinet_blob_func); g_test_add_func ("/GCab/cabinet{signature}", gcab_test_cabinet_signature_func); + g_test_add_func ("/GCab/cabinet{allowed-compression}", gcab_test_cabinet_allowed_compression_func); return g_test_run (); } |