summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2023-01-04 15:33:07 +0000
committerMarc-André Lureau <marcandre.lureau@gmail.com>2023-01-04 15:33:07 +0000
commit3b6942d7ff3bb0b1671f894aba2010b384809fc4 (patch)
tree3327b253420b7b16ace30303c9b344e9f6f671d1
parent274e0bba51d007f8b5b4c09b26ec50b5999efdfb (diff)
parent690377dfae69eeea54826fbd2c7156e2147d2cee (diff)
downloadgcab-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.c48
-rw-r--r--libgcab/gcab-cabinet.h2
-rw-r--r--libgcab/libgcab.syms4
-rw-r--r--meson.build2
-rw-r--r--tests/gcab-self-test.c42
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 ();
}