diff options
author | Simon Tatham <anakin@pobox.com> | 2018-05-14 18:14:12 +0100 |
---|---|---|
committer | Simon Tatham <anakin@pobox.com> | 2018-05-14 18:14:12 +0100 |
commit | 1c1c3850e8a54938f41afb5e49a9176b229a3a88 (patch) | |
tree | 87afe7756a633bad27bb8ae19fda6704de614c34 | |
parent | 66f1f5d2bff9900a62db381c8718acb1982f4753 (diff) | |
download | wix-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.c | 103 |
1 files changed, 81 insertions, 22 deletions
@@ -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 | */ | ||
49 | typedef uint32_t MsiHandle; | ||
50 | static void **msi_handles = NULL; | ||
51 | static size_t n_msi_handles = 0, msi_handles_size = 0; | ||
52 | |||
53 | static 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 | |||
71 | static 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 | |||
82 | static 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 | ||
45 | uint32_t MsiOpenDatabaseW(const char16_t *filename, | 89 | uint32_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 | ||
71 | uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder, | 115 | uint32_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 | ||
95 | uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, | 139 | static 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 | |||
146 | uint32_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 | ||
125 | uint32_t MsiViewExecute(MsiView *view, void *params) | 176 | uint32_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 | ||
137 | MsiRecord *MsiCreateRecord(uint32_t nparams) | 188 | static MsiRecord *lookup_handle_record(MsiHandle handle) |
189 | { | ||
190 | MsiRecord *toret = lookup_handle(handle); | ||
191 | assert(toret->t.type == RECORD); | ||
192 | return toret; | ||
193 | } | ||
194 | |||
195 | MsiHandle 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 | ||
148 | uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value) | 206 | uint32_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 | ||
157 | uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path) | 215 | uint32_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 | ||
166 | uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) | 224 | uint32_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 | ||
187 | uint32_t MsiCloseHandle(MsiTypePrefix *t) | 245 | uint32_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 | ||
197 | uint32_t MsiDatabaseCommit(MsiMainCtx *ctx) | 256 | uint32_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(" '"); |