aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2018-05-14 18:14:12 +0100
committerSimon Tatham <anakin@pobox.com>2018-05-14 18:14:12 +0100
commit1c1c3850e8a54938f41afb5e49a9176b229a3a88 (patch)
tree87afe7756a633bad27bb8ae19fda6704de614c34
parent66f1f5d2bff9900a62db381c8718acb1982f4753 (diff)
downloadwix-on-linux-1c1c3850e8a54938f41afb5e49a9176b229a3a88.tar.gz
wix-on-linux-1c1c3850e8a54938f41afb5e49a9176b229a3a88.tar.bz2
wix-on-linux-1c1c3850e8a54938f41afb5e49a9176b229a3a88.zip
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.
-rw-r--r--makemsi.c103
1 files 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 {
41 int nargs, argsize; 41 int nargs, argsize;
42} MsiMainCtx; 42} MsiMainCtx;
43 43
44/*
45 * The Msi functions will expect to identify things by 32-bit handles,
46 * not machine-word sized pointers. So we must keep a list of handles
47 * we've allocated.
48 */
49typedef uint32_t MsiHandle;
50static void **msi_handles = NULL;
51static size_t n_msi_handles = 0, msi_handles_size = 0;
52
53static MsiHandle make_handle(void *ptr)
54{
55 size_t index;
56
57 if (n_msi_handles >= msi_handles_size) {
58 msi_handles_size = n_msi_handles * 5 / 4 + 512;
59 msi_handles = sresize(msi_handles, msi_handles_size, void *);
60 }
61
62 index = n_msi_handles++;
63 msi_handles[index] = ptr;
64
65 /*
66 * A mild error-correcting code, to ensure our handles make sense.
67 */
68 return index * 59 + 17;
69}
70
71static void *lookup_handle(MsiHandle h)
72{
73 size_t index;
74
75 assert(h % 59 == 17);
76 index = h / 59;
77
78 assert(index < n_msi_handles);
79 return msi_handles[index];
80}
81
82static MsiMainCtx *lookup_handle_main(MsiHandle handle)
83{
84 MsiMainCtx *toret = lookup_handle(handle);
85 assert(toret->t.type == MAIN);
86 return toret;
87}
44 88
45uint32_t MsiOpenDatabaseW(const char16_t *filename, 89uint32_t MsiOpenDatabaseW(const char16_t *filename,
46 const char16_t *persist, 90 const char16_t *persist,
47 MsiMainCtx **out_ctx) 91 MsiHandle *out_handle)
48{ 92{
49 MsiMainCtx *ctx = snew(MsiMainCtx); 93 MsiMainCtx *ctx = snew(MsiMainCtx);
50 ctx->t.type = MAIN; 94 ctx->t.type = MAIN;
@@ -64,14 +108,14 @@ uint32_t MsiOpenDatabaseW(const char16_t *filename,
64 ctx->args[ctx->nargs++] = dupstr(ctx->tempdir); 108 ctx->args[ctx->nargs++] = dupstr(ctx->tempdir);
65 ctx->args[ctx->nargs++] = dupstr("msibuild"); 109 ctx->args[ctx->nargs++] = dupstr("msibuild");
66 ctx->args[ctx->nargs++] = dupstr(ctx->outfile); 110 ctx->args[ctx->nargs++] = dupstr(ctx->outfile);
67 *out_ctx = ctx; 111 *out_handle = make_handle(ctx);
68 return 0; 112 return 0;
69} 113}
70 114
71uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder, 115uint32_t MsiDatabaseImportW(MsiHandle handle, const char16_t *folder,
72 const char16_t *file) 116 const char16_t *file)
73{ 117{
74 assert(ctx->t.type == MAIN); 118 MsiMainCtx *ctx = lookup_handle_main(handle);
75 system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"", 119 system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"",
76 ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL); 120 ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL);
77 if (ctx->nargs + 2 >= ctx->argsize) { 121 if (ctx->nargs + 2 >= ctx->argsize) {
@@ -92,10 +136,17 @@ typedef struct MsiView {
92 MsiMainCtx *ctx; 136 MsiMainCtx *ctx;
93} MsiView; 137} MsiView;
94 138
95uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, 139static MsiView *lookup_handle_view(MsiHandle handle)
96 MsiView **outview)
97{ 140{
98 assert(ctx->t.type == MAIN); 141 MsiView *toret = lookup_handle(handle);
142 assert(toret->t.type == VIEW);
143 return toret;
144}
145
146uint32_t MsiDatabaseOpenViewW(MsiHandle handle, const char16_t *query,
147 MsiHandle *outhandle)
148{
149 MsiMainCtx *ctx = lookup_handle_main(handle);
99 MsiView *view = snew(MsiView); 150 MsiView *view = snew(MsiView);
100 view->t.type = VIEW; 151 view->t.type = VIEW;
101 view->ctx = ctx; 152 view->ctx = ctx;
@@ -118,13 +169,13 @@ uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query,
118 if (mkdir(view->targetdir, 0777) < 0) 169 if (mkdir(view->targetdir, 0777) < 0)
119 err(1, "%s: mkdir", view->targetdir); 170 err(1, "%s: mkdir", view->targetdir);
120 } 171 }
121 *outview = view; 172 *outhandle = make_handle(view);
122 return 0; 173 return 0;
123} 174}
124 175
125uint32_t MsiViewExecute(MsiView *view, void *params) 176uint32_t MsiViewExecute(MsiHandle handle, void *params)
126{ 177{
127 assert(view->t.type == VIEW); 178 lookup_handle_view(handle);
128 return 0; 179 return 0;
129} 180}
130 181
@@ -134,7 +185,14 @@ typedef struct MsiRecord {
134 char *name, *data; 185 char *name, *data;
135} MsiRecord; 186} MsiRecord;
136 187
137MsiRecord *MsiCreateRecord(uint32_t nparams) 188static MsiRecord *lookup_handle_record(MsiHandle handle)
189{
190 MsiRecord *toret = lookup_handle(handle);
191 assert(toret->t.type == RECORD);
192 return toret;
193}
194
195MsiHandle MsiCreateRecord(uint32_t nparams)
138{ 196{
139 MsiRecord *rec = snew(MsiRecord); 197 MsiRecord *rec = snew(MsiRecord);
140 rec->t.type = RECORD; 198 rec->t.type = RECORD;
@@ -142,31 +200,31 @@ MsiRecord *MsiCreateRecord(uint32_t nparams)
142 if (nparams != 2) 200 if (nparams != 2)
143 errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams); 201 errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams);
144 rec->name = rec->data = NULL; 202 rec->name = rec->data = NULL;
145 return rec; 203 return make_handle(rec);
146} 204}
147 205
148uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value) 206uint32_t MsiRecordSetStringW(MsiHandle handle, uint32_t field, char16_t *value)
149{ 207{
150 assert(rec->t.type == RECORD); 208 MsiRecord *rec = lookup_handle_record(handle);
151 if (field != 1) 209 if (field != 1)
152 errx(1, "bad MsiRecordSetString param index %u", (unsigned)field); 210 errx(1, "bad MsiRecordSetString param index %u", (unsigned)field);
153 rec->name = ascii(value, false); 211 rec->name = ascii(value, false);
154 return 0; 212 return 0;
155} 213}
156 214
157uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path) 215uint32_t MsiRecordSetStreamW(MsiHandle handle, uint32_t field, char16_t *path)
158{ 216{
159 assert(rec->t.type == RECORD); 217 MsiRecord *rec = lookup_handle_record(handle);
160 if (field != 2) 218 if (field != 2)
161 errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field); 219 errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field);
162 rec->data = ascii(path, true); 220 rec->data = ascii(path, true);
163 return 0; 221 return 0;
164} 222}
165 223
166uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) 224uint32_t MsiViewModify(MsiHandle viewhandle, uint32_t mode, MsiHandle rechandle)
167{ 225{
168 assert(view->t.type == VIEW); 226 MsiView *view = lookup_handle_view(viewhandle);
169 assert(rec->t.type == RECORD); 227 MsiRecord *rec = lookup_handle_record(rechandle);
170 if (view->fp) { 228 if (view->fp) {
171 system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"", 229 system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"",
172 rec->data, view->targetdir, rec->name, cNULL); 230 rec->data, view->targetdir, rec->name, cNULL);
@@ -184,8 +242,9 @@ uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec)
184 return 0; 242 return 0;
185} 243}
186 244
187uint32_t MsiCloseHandle(MsiTypePrefix *t) 245uint32_t MsiCloseHandle(MsiHandle handle)
188{ 246{
247 MsiTypePrefix *t = lookup_handle(handle);
189 if (t->type == VIEW) { 248 if (t->type == VIEW) {
190 MsiView *view = (MsiView *)t; 249 MsiView *view = (MsiView *)t;
191 if (view->fp) 250 if (view->fp)
@@ -194,9 +253,9 @@ uint32_t MsiCloseHandle(MsiTypePrefix *t)
194 return 0; 253 return 0;
195} 254}
196 255
197uint32_t MsiDatabaseCommit(MsiMainCtx *ctx) 256uint32_t MsiDatabaseCommit(MsiHandle handle)
198{ 257{
199 assert(ctx->t.type == MAIN); 258 MsiMainCtx *ctx = lookup_handle_main(handle);
200 printf("commit:"); 259 printf("commit:");
201 for (int i = 0; i < ctx->nargs; i++) { 260 for (int i = 0; i < ctx->nargs; i++) {
202 printf(" '"); 261 printf(" '");