From acce8e2556251fbe9f2bda31cc6f2ceef1e18a3f Mon Sep 17 00:00:00 2001 From: Joshua Wright Date: Wed, 26 Aug 2026 10:31:21 -0500 Subject: [PATCH] Fix out-of-bounds dltab in the WASI dlopen shim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dltab was a tentative one-element array ("dict_t* dltab[]") indexed past its end, and slot 0 was never assigned: the first library was stored at dltab[1] while the lookup loop read dltab[0..dltab_index). Every dlopen lookup therefore dereferenced a NULL dict, i.e. guest address 0. That happens to be harmless while address 0 holds zeros (the dict's len field reads as 0), which is why the socket-file transport never noticed. With the CMA wire channel, live request bytes sit at the bottom of linear memory, so the NULL-dict read picks up garbage lengths and entry pointers and traps — reproducible as a crash on the first CREATE EXTENSION issued over CMA. Make dltab a real fixed-size array, keep every slot initialized, check the existing-library branch against index >= 0 (slot 0 is valid), and return stable 1-based handles. --- .../sdk_port-wasi/sdk_port-wasi-dlfcn.c | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/wasm-build/sdk_port-wasi/sdk_port-wasi-dlfcn.c b/wasm-build/sdk_port-wasi/sdk_port-wasi-dlfcn.c index 44dac9e5e3cd2..034651dacf2b1 100644 --- a/wasm-build/sdk_port-wasi/sdk_port-wasi-dlfcn.c +++ b/wasm-build/sdk_port-wasi/sdk_port-wasi-dlfcn.c @@ -81,7 +81,16 @@ ends_with(const char *str, const char *suffix) // dlfcn.h -volatile dict_t* dltab[]; +/* dltab was a tentative (1-element) array indexed past its end, and slot + * 0 was never assigned: the first library landed at dltab[1] while the + * lookup loop read dltab[0..dltab_index), so every lookup dereferenced a + * NULL dict — i.e. guest address 0. That is harmless while address 0 + * holds zeros, but the CMA wire channel places live request bytes at the + * bottom of memory, turning the NULL-dict read into wild loads and traps + * (observed as a crash on the first CREATE EXTENSION over CMA). Use a + * real array and keep every slot initialized. */ +#define DLTAB_MAX 64 +static dict_t dltab[DLTAB_MAX]; volatile int dltab_index = 0; void * @@ -132,8 +141,8 @@ dlopen(const char *filename, int flags) { dict_t tab = NULL; fprintf(stderr,"void *dlopen(const char *filename = %s, int flags=%d)\n", filename, flags); for (int i=0; i< dltab_index; i++) { - if ( dict_find_index(dltab[i], filename) > 0 ) - return (void *)i; + if ( dltab[i] && dict_find_index(dltab[i], filename) >= 0 ) + return (void *)(i + 1); } printf("dlopen: new lib '%s'\n", filename ); if ( ends_with(filename,"/plpgsql.so") ){ @@ -141,9 +150,11 @@ dlopen(const char *filename, int flags) { _PG_init(); } + if (dltab_index >= DLTAB_MAX) + return NULL; tab = dict_new(); - dict_add(tab, filename, dltab_index++ ); - dltab[dltab_index] = tab; + dict_add(tab, filename, dltab_index); + dltab[dltab_index++] = tab; return (void *)dltab_index; }