Skip to content
This repository was archived by the owner on May 24, 2026. It is now read-only.

Commit 3fd2e02

Browse files
caesayclaude
andcommitted
Add global lock to cabinet operations for thread safety
CabinetBuilder runs multiple threads concurrently. Cabinet functions (CabAddFile, CabFlush, CabEnumerate, CabExtract) call into GIO/gcab which is not thread-safe. Add libmsi_global_lock around all GIO-calling cabinet operations to prevent concurrent access crashes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c59bd3f commit 3fd2e02

1 file changed

Lines changed: 29 additions & 3 deletions

File tree

msi-interop/msi_cab.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "msi_cab.h"
1111
#include "string_utils.h"
12+
#include "handle_table.h"
1213

1314
#include <gcab-cabinet.h>
1415
#include <gcab-folder.h>
@@ -206,6 +207,8 @@ CabAddFile(CABHANDLE handle,
206207
return CAB_ERROR_INVALID_PARAM;
207208
}
208209

210+
libmsi_global_lock();
211+
209212
/* Query file size on disk */
210213
int64_t file_size = 0;
211214
GFile *gfile = g_file_new_for_path(file_path_utf8);
@@ -224,6 +227,7 @@ CabAddFile(CABHANDLE handle,
224227

225228
g_ptr_array_add(ctx->files, entry);
226229

230+
libmsi_global_unlock();
227231
return CAB_SUCCESS;
228232
}
229233

@@ -343,10 +347,14 @@ CabFlush(CABHANDLE handle,
343347
if (handle == 0)
344348
return CAB_ERROR_INVALID_PARAM;
345349

350+
libmsi_global_lock();
351+
346352
CabContext *ctx = (CabContext *)(uintptr_t)handle;
347353

348-
if (out_count == NULL)
354+
if (out_count == NULL) {
355+
libmsi_global_unlock();
349356
return CAB_ERROR_INVALID_PARAM;
357+
}
350358

351359
*out_count = 0;
352360

@@ -357,8 +365,10 @@ CabFlush(CABHANDLE handle,
357365
gboolean ok = write_single_cabinet(ctx, 0, 0, ctx->output_path, &error);
358366
g_clear_error(&error);
359367

360-
if (!ok)
368+
if (!ok) {
369+
libmsi_global_unlock();
361370
return CAB_ERROR_FUNCTION_FAILED;
371+
}
362372

363373
/* Report the single empty cabinet */
364374
WCHAR *cab_name_w = utf8_to_utf16(ctx->cab_basename, NULL);
@@ -371,6 +381,7 @@ CabFlush(CABHANDLE handle,
371381
out_cabs[0].first_file_token = (const wchar_t *)g_ptr_array_index(ctx->result_tokens, 0);
372382
}
373383
*out_count = 1;
384+
libmsi_global_unlock();
374385
return CAB_SUCCESS;
375386
}
376387

@@ -428,6 +439,7 @@ CabFlush(CABHANDLE handle,
428439
g_free(cab_name);
429440
g_clear_error(&error);
430441
g_array_free(partitions, TRUE);
442+
libmsi_global_unlock();
431443
return CAB_ERROR_FUNCTION_FAILED;
432444
}
433445

@@ -462,6 +474,7 @@ CabFlush(CABHANDLE handle,
462474

463475
*out_count = num_cabs;
464476

477+
libmsi_global_unlock();
465478
return CAB_SUCCESS;
466479
}
467480

@@ -503,9 +516,13 @@ CabEnumerate(const wchar_t *cab_path,
503516
if (cab_path == NULL || callback == NULL)
504517
return CAB_ERROR_INVALID_PARAM;
505518

519+
libmsi_global_lock();
520+
506521
char *path_utf8 = wchar_to_utf8(cab_path);
507-
if (path_utf8 == NULL)
522+
if (path_utf8 == NULL) {
523+
libmsi_global_unlock();
508524
return CAB_ERROR_INVALID_PARAM;
525+
}
509526

510527
GFile *gfile = g_file_new_for_path(path_utf8);
511528
GError *error = NULL;
@@ -516,6 +533,7 @@ CabEnumerate(const wchar_t *cab_path,
516533

517534
if (fis == NULL) {
518535
g_clear_error(&error);
536+
libmsi_global_unlock();
519537
return CAB_ERROR_OPEN_FAILED;
520538
}
521539

@@ -524,6 +542,7 @@ CabEnumerate(const wchar_t *cab_path,
524542
g_clear_error(&error);
525543
g_object_unref(fis);
526544
g_object_unref(cab);
545+
libmsi_global_unlock();
527546
return CAB_ERROR_FUNCTION_FAILED;
528547
}
529548

@@ -580,6 +599,7 @@ CabEnumerate(const wchar_t *cab_path,
580599

581600
done:
582601
g_object_unref(cab);
602+
libmsi_global_unlock();
583603
return result;
584604
}
585605

@@ -631,6 +651,8 @@ CabExtract(const wchar_t *cab_path,
631651
return CAB_ERROR_INVALID_PARAM;
632652
}
633653

654+
libmsi_global_lock();
655+
634656
/* Open and load the cabinet */
635657
GFile *gfile = g_file_new_for_path(path_utf8);
636658
GError *error = NULL;
@@ -642,6 +664,7 @@ CabExtract(const wchar_t *cab_path,
642664
if (fis == NULL) {
643665
g_clear_error(&error);
644666
g_free(outdir_utf8);
667+
libmsi_global_unlock();
645668
return CAB_ERROR_OPEN_FAILED;
646669
}
647670

@@ -651,6 +674,7 @@ CabExtract(const wchar_t *cab_path,
651674
g_object_unref(fis);
652675
g_object_unref(cab);
653676
g_free(outdir_utf8);
677+
libmsi_global_unlock();
654678
return CAB_ERROR_FUNCTION_FAILED;
655679
}
656680
g_object_unref(fis);
@@ -676,6 +700,7 @@ CabExtract(const wchar_t *cab_path,
676700
g_object_unref(out_gfile);
677701
g_object_unref(cab);
678702
g_clear_error(&error);
703+
libmsi_global_unlock();
679704
return CAB_ERROR_FUNCTION_FAILED;
680705
}
681706

@@ -776,6 +801,7 @@ CabExtract(const wchar_t *cab_path,
776801
g_object_unref(out_gfile);
777802
g_object_unref(cab);
778803

804+
libmsi_global_unlock();
779805
return CAB_SUCCESS;
780806
}
781807

0 commit comments

Comments
 (0)