From 1c1c3850e8a54938f41afb5e49a9176b229a3a88 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 14 May 2018 18:14:12 +0100 Subject: Stop using real pointers as handles in makemsi.c. Upgrading to Ubuntu 18.04, which seems to have become more prone to allocating process memory above the 4G boundary, has revealed that the client code of the phony msi.dll functions is not in fact prepared to accept arbitrary machine-word sized pointer values. It's expecting 32-bit handles, so we were segfaulting because MsiDatabaseImportW was only being given the bottom 32 bits of the 64-bit pointer that MsiOpenDatabaseW had returned. So now I just keep a trivial registry of small integer handle values and the pointers they map to. I don't even bother to recycle them - the process isn't expected to run for long enough for me to care. --- makemsi.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 22 deletions(-) diff --git a/makemsi.c b/makemsi.c index 8b78448..a301319 100644 --- a/makemsi.c +++ b/makemsi.c @@ -41,10 +41,54 @@ typedef struct MsiMainCtx { int nargs, argsize; } MsiMainCtx; +/* + * The Msi functions will expect to identify things by 32-bit handles, + * not machine-word sized pointers. So we must keep a list of handles + * we've allocated. + */ +typedef uint32_t MsiHandle; +static void **msi_handles = NULL; +static size_t n_msi_handles = 0, msi_handles_size = 0; + +static MsiHandle make_handle(void *ptr) +{ + size_t index; + + if (n_msi_handles >= msi_handles_size) { + msi_handles_size = n_msi_handles * 5 / 4 + 512; + msi_handles = sresize(msi_handles, msi_handles_size, void *); + } + + index = n_msi_handles++; + msi_handles[index] = ptr; + + /* + * A mild error-correcting code, to ensure our handles make sense. + */ + return index * 59 + 17; +} + +static void *lookup_handle(MsiHandle h) +{ + size_t index; + + assert(h % 59 == 17); + index = h / 59; + + assert(index < n_msi_handles); + return msi_handles[index]; +} + +static MsiMainCtx *lookup_handle_main(MsiHandle handle) +{ + MsiMainCtx *toret = lookup_handle(handle); + assert(toret->t.type == MAIN); + return toret; +} uint32_t MsiOpenDatabaseW(const char16_t *filename, const char16_t *persist, - MsiMainCtx **out_ctx) + MsiHandle *out_handle) { MsiMainCtx *ctx = snew(MsiMainCtx); ctx->t.type = MAIN; @@ -64,14 +108,14 @@ uint32_t MsiOpenDatabaseW(const char16_t *filename, ctx->args[ctx->nargs++] = dupstr(ctx->tempdir); ctx->args[ctx->nargs++] = dupstr("msibuild"); ctx->args[ctx->nargs++] = dupstr(ctx->outfile); - *out_ctx = ctx; + *out_handle = make_handle(ctx); return 0; } -uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder, +uint32_t MsiDatabaseImportW(MsiHandle handle, const char16_t *folder, const char16_t *file) { - assert(ctx->t.type == MAIN); + MsiMainCtx *ctx = lookup_handle_main(handle); system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"", ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL); if (ctx->nargs + 2 >= ctx->argsize) { @@ -92,10 +136,17 @@ typedef struct MsiView { MsiMainCtx *ctx; } MsiView; -uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, - MsiView **outview) +static MsiView *lookup_handle_view(MsiHandle handle) { - assert(ctx->t.type == MAIN); + MsiView *toret = lookup_handle(handle); + assert(toret->t.type == VIEW); + return toret; +} + +uint32_t MsiDatabaseOpenViewW(MsiHandle handle, const char16_t *query, + MsiHandle *outhandle) +{ + MsiMainCtx *ctx = lookup_handle_main(handle); MsiView *view = snew(MsiView); view->t.type = VIEW; view->ctx = ctx; @@ -118,13 +169,13 @@ uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, if (mkdir(view->targetdir, 0777) < 0) err(1, "%s: mkdir", view->targetdir); } - *outview = view; + *outhandle = make_handle(view); return 0; } -uint32_t MsiViewExecute(MsiView *view, void *params) +uint32_t MsiViewExecute(MsiHandle handle, void *params) { - assert(view->t.type == VIEW); + lookup_handle_view(handle); return 0; } @@ -134,7 +185,14 @@ typedef struct MsiRecord { char *name, *data; } MsiRecord; -MsiRecord *MsiCreateRecord(uint32_t nparams) +static MsiRecord *lookup_handle_record(MsiHandle handle) +{ + MsiRecord *toret = lookup_handle(handle); + assert(toret->t.type == RECORD); + return toret; +} + +MsiHandle MsiCreateRecord(uint32_t nparams) { MsiRecord *rec = snew(MsiRecord); rec->t.type = RECORD; @@ -142,31 +200,31 @@ MsiRecord *MsiCreateRecord(uint32_t nparams) if (nparams != 2) errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams); rec->name = rec->data = NULL; - return rec; + return make_handle(rec); } -uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value) +uint32_t MsiRecordSetStringW(MsiHandle handle, uint32_t field, char16_t *value) { - assert(rec->t.type == RECORD); + MsiRecord *rec = lookup_handle_record(handle); if (field != 1) errx(1, "bad MsiRecordSetString param index %u", (unsigned)field); rec->name = ascii(value, false); return 0; } -uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path) +uint32_t MsiRecordSetStreamW(MsiHandle handle, uint32_t field, char16_t *path) { - assert(rec->t.type == RECORD); + MsiRecord *rec = lookup_handle_record(handle); if (field != 2) errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field); rec->data = ascii(path, true); return 0; } -uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) +uint32_t MsiViewModify(MsiHandle viewhandle, uint32_t mode, MsiHandle rechandle) { - assert(view->t.type == VIEW); - assert(rec->t.type == RECORD); + MsiView *view = lookup_handle_view(viewhandle); + MsiRecord *rec = lookup_handle_record(rechandle); if (view->fp) { system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"", rec->data, view->targetdir, rec->name, cNULL); @@ -184,8 +242,9 @@ uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) return 0; } -uint32_t MsiCloseHandle(MsiTypePrefix *t) +uint32_t MsiCloseHandle(MsiHandle handle) { + MsiTypePrefix *t = lookup_handle(handle); if (t->type == VIEW) { MsiView *view = (MsiView *)t; if (view->fp) @@ -194,9 +253,9 @@ uint32_t MsiCloseHandle(MsiTypePrefix *t) return 0; } -uint32_t MsiDatabaseCommit(MsiMainCtx *ctx) +uint32_t MsiDatabaseCommit(MsiHandle handle) { - assert(ctx->t.type == MAIN); + MsiMainCtx *ctx = lookup_handle_main(handle); printf("commit:"); for (int i = 0; i < ctx->nargs; i++) { printf(" '"); -- cgit v1.2.3-55-g6feb