Skip to content

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)