From 7622c4915bfb87fd30bf98c748ca8f2819622cd4 Mon Sep 17 00:00:00 2001 From: SirHumza <204067870+SirHumza@users.noreply.github.com> Date: Fri, 14 Aug 2026 10:30:25 +0200 Subject: [PATCH] fix(jsonlite/discord): two memory-safety bugs found via host ASan 1. jsonlite.c: jl_stringify started with out=NULL but emit's growth check (1 > cap) never triggered realloc, so the first '{' wrote to NULL -> guaranteed crash on first IDENTIFY/presence build. Pre-allocate. Also grow the buffer in the no-child fallback path. 2. discord.c: jl_obj_set(dd,"status","online") and "invisible" passed a const char* where jl_val_t* is expected. Compiles (both are pointers) but pair->child points at rodata -> jl_free reads garbage struct fields, double-free/global-buffer-overflow caught by ASan. Verified with host-side ASan tests: presence payload roundtrips clean, 1000 READY parse/free cycles leak-free, b64 known-answer vectors pass. --- PS4RP/discord.c | 4 ++-- PS4RP/jsonlite.c | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/PS4RP/discord.c b/PS4RP/discord.c index 169fdad..2b367bf 100644 --- a/PS4RP/discord.c +++ b/PS4RP/discord.c @@ -87,7 +87,7 @@ int discord_set_presence(discord_t *d, const char *state, const char *details, jl_obj_set(act,"assets",assets); jl_obj_set(dd,"activities",jl_new_array()); jl_arr_push(jl_obj_get(dd,"activities"), act); - jl_obj_set(dd,"status","online"); + jl_obj_set(dd,"status",jl_new_string("online")); jl_obj_set(dd,"since",jl_new_number((double)time(NULL))); jl_obj_set(dd,"afk",jl_new_bool(0)); jl_val_t *root=jl_new_object(); @@ -101,7 +101,7 @@ int discord_set_presence(discord_t *d, const char *state, const char *details, int discord_clear_presence(discord_t *d){ jl_val_t *dd=jl_new_object(); jl_obj_set(dd,"activities",jl_new_array()); - jl_obj_set(dd,"status","invisible"); + jl_obj_set(dd,"status",jl_new_string("invisible")); jl_val_t *root=jl_new_object(); jl_obj_set(root,"op",jl_new_number(3)); jl_obj_set(root,"d",dd); diff --git a/PS4RP/jsonlite.c b/PS4RP/jsonlite.c index 6bb4711..5d6ac55 100644 --- a/PS4RP/jsonlite.c +++ b/PS4RP/jsonlite.c @@ -205,7 +205,9 @@ static void emit(jl_val_t *v, char **out, size_t *cap, size_t *len){ escstr(p->str,out,cap,len); size_t l3=*len+1; if(l3>*cap){*cap=l3*2;*out=realloc(*out,*cap);} (*out)[(*len)++]=':'; /* value is the pair's child OR the pair holds value via child */ - if(p->child) emit(p->child,out,cap,len); else { *out[*len]='n'; /* shouldn't happen */ } + if(p->child) emit(p->child,out,cap,len); else { + size_t lz=*len+1; if(lz>*cap){*cap=lz*2;*out=realloc(*out,*cap);} (*out)[(*len)++]='n'; + } /* for non-pair objects where a STRING key sits directly: handled above via child */ } p=p->next; } l=*len+1; if(l>*cap){*cap=l*2;*out=realloc(*out,*cap);} (*out)[(*len)++]='}'; return; } @@ -216,7 +218,8 @@ static void emit(jl_val_t *v, char **out, size_t *cap, size_t *len){ } char *jl_stringify(const jl_val_t *v){ - char *out=NULL; size_t cap=256,len=0; + char *out=(char*)malloc(256); if(!out) return NULL; + size_t cap=256,len=0; emit((jl_val_t*)v,&out,&cap,&len); if(!out){ out=(char*)malloc(1); out[0]=0; } else { char *t=(char*)realloc(out,len+1); t[len]=0; out=t; }