Skip to content

Fix undefined behavior in callback functions' parameter passing #104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions src/arg_date.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@

char* arg_strptime(const char* buf, const char* fmt, struct tm* tm);

static void arg_date_resetfn(struct arg_date* parent) {
static void arg_date_resetfn(void* parent_) {
struct arg_date* parent = parent_;
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}

static int arg_date_scanfn(struct arg_date* parent, const char* argval) {
static int arg_date_scanfn(void* parent_, const char* argval) {
struct arg_date* parent = parent_;
int errorcode = 0;

if (parent->count == parent->hdr.maxcount) {
Expand All @@ -70,14 +72,16 @@ static int arg_date_scanfn(struct arg_date* parent, const char* argval) {
return errorcode;
}

static int arg_date_checkfn(struct arg_date* parent) {
static int arg_date_checkfn(void* parent_) {
struct arg_date* parent = parent_;
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;

ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}

static void arg_date_errorfn(struct arg_date* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
static void arg_date_errorfn(void* parent_, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
struct arg_date* parent = parent_;
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
Expand Down Expand Up @@ -147,10 +151,10 @@ arg_daten(const char* shortopts, const char* longopts, const char* format, const
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_date_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_date_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_date_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_date_errorfn;
result->hdr.resetfn = arg_date_resetfn;
result->hdr.scanfn = arg_date_scanfn;
result->hdr.checkfn = arg_date_checkfn;
result->hdr.errorfn = arg_date_errorfn;

/* store the tmval[maxcount] array immediately after the arg_date struct */
result->tmval = (struct tm*)(result + 1);
Expand Down
20 changes: 12 additions & 8 deletions src/arg_dbl.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@

#include <stdlib.h>

static void arg_dbl_resetfn(struct arg_dbl* parent) {
static void arg_dbl_resetfn(void* parent_) {
struct arg_dbl* parent = parent_;
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}

static int arg_dbl_scanfn(struct arg_dbl* parent, const char* argval) {
static int arg_dbl_scanfn(void* parent_, const char* argval) {
struct arg_dbl* parent = parent_;
int errorcode = 0;

if (parent->count == parent->hdr.maxcount) {
Expand Down Expand Up @@ -72,14 +74,16 @@ static int arg_dbl_scanfn(struct arg_dbl* parent, const char* argval) {
return errorcode;
}

static int arg_dbl_checkfn(struct arg_dbl* parent) {
static int arg_dbl_checkfn(void* parent_) {
struct arg_dbl* parent = parent_;
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;

ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}

static void arg_dbl_errorfn(struct arg_dbl* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
static void arg_dbl_errorfn(void* parent_, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
struct arg_dbl* parent = parent_;
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
Expand Down Expand Up @@ -137,10 +141,10 @@ struct arg_dbl* arg_dbln(const char* shortopts, const char* longopts, const char
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_dbl_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_dbl_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_dbl_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_dbl_errorfn;
result->hdr.resetfn = arg_dbl_resetfn;
result->hdr.scanfn = arg_dbl_scanfn;
result->hdr.checkfn = arg_dbl_checkfn;
result->hdr.errorfn = arg_dbl_errorfn;

/* Store the dval[maxcount] array on the first double boundary that
* immediately follows the arg_dbl struct. We do the memory alignment
Expand Down
7 changes: 4 additions & 3 deletions src/arg_end.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@

#include <stdlib.h>

static void arg_end_resetfn(struct arg_end* parent) {
static void arg_end_resetfn(void* parent_) {
struct arg_end* parent = parent_;
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
Expand Down Expand Up @@ -94,10 +95,10 @@ struct arg_end* arg_end(int maxcount) {
result->hdr.mincount = 1;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_end_resetfn;
result->hdr.resetfn = arg_end_resetfn;
result->hdr.scanfn = NULL;
result->hdr.checkfn = NULL;
result->hdr.errorfn = (arg_errorfn*)arg_end_errorfn;
result->hdr.errorfn = arg_end_errorfn;

/* store error[maxcount] array immediately after struct arg_end */
result->error = (int*)(result + 1);
Expand Down
20 changes: 12 additions & 8 deletions src/arg_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
#define FILESEPARATOR2 '/'
#endif

static void arg_file_resetfn(struct arg_file* parent) {
static void arg_file_resetfn(void* parent_) {
struct arg_file* parent = parent_;
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
Expand Down Expand Up @@ -98,7 +99,8 @@ static const char* arg_extension(const char* basename) {
return result;
}

static int arg_file_scanfn(struct arg_file* parent, const char* argval) {
static int arg_file_scanfn(void* parent_, const char* argval) {
struct arg_file* parent = parent_;
int errorcode = 0;

if (parent->count == parent->hdr.maxcount) {
Expand All @@ -121,14 +123,16 @@ static int arg_file_scanfn(struct arg_file* parent, const char* argval) {
return errorcode;
}

static int arg_file_checkfn(struct arg_file* parent) {
static int arg_file_checkfn(void* parent_) {
struct arg_file* parent = parent_;
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;

ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}

static void arg_file_errorfn(struct arg_file* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
static void arg_file_errorfn(void* parent_, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
struct arg_file* parent = parent_;
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
Expand Down Expand Up @@ -185,10 +189,10 @@ struct arg_file* arg_filen(const char* shortopts, const char* longopts, const ch
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_file_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_file_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_file_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_file_errorfn;
result->hdr.resetfn = arg_file_resetfn;
result->hdr.scanfn = arg_file_scanfn;
result->hdr.checkfn = arg_file_checkfn;
result->hdr.errorfn = arg_file_errorfn;

/* store the filename,basename,extension arrays immediately after the arg_file struct */
result->filename = (const char**)(result + 1);
Expand Down
20 changes: 12 additions & 8 deletions src/arg_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
#include <limits.h>
#include <stdlib.h>

static void arg_int_resetfn(struct arg_int* parent) {
static void arg_int_resetfn(void* parent_) {
struct arg_int* parent = parent_;
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}
Expand Down Expand Up @@ -136,7 +137,8 @@ static int detectsuffix(const char* str, const char* suffix) {
return (*str == '\0') ? 1 : 0;
}

static int arg_int_scanfn(struct arg_int* parent, const char* argval) {
static int arg_int_scanfn(void* parent_, const char* argval) {
struct arg_int* parent = parent_;
int errorcode = 0;

if (parent->count == parent->hdr.maxcount) {
Expand Down Expand Up @@ -207,13 +209,15 @@ static int arg_int_scanfn(struct arg_int* parent, const char* argval) {
return errorcode;
}

static int arg_int_checkfn(struct arg_int* parent) {
static int arg_int_checkfn(void* parent_) {
struct arg_int* parent = parent_;
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
/*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/
return errorcode;
}

static void arg_int_errorfn(struct arg_int* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
static void arg_int_errorfn(void* parent_, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
struct arg_int* parent = parent_;
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
Expand Down Expand Up @@ -275,10 +279,10 @@ struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_int_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_int_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_int_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_int_errorfn;
result->hdr.resetfn = arg_int_resetfn;
result->hdr.scanfn = arg_int_scanfn;
result->hdr.checkfn = arg_int_checkfn;
result->hdr.errorfn = arg_int_errorfn;

/* store the ival[maxcount] array immediately after the arg_int struct */
result->ival = (int*)(result + 1);
Expand Down
20 changes: 12 additions & 8 deletions src/arg_lit.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@

#include <stdlib.h>

static void arg_lit_resetfn(struct arg_lit* parent) {
static void arg_lit_resetfn(void* parent_) {
struct arg_lit* parent = parent_;
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}

static int arg_lit_scanfn(struct arg_lit* parent, const char* argval) {
static int arg_lit_scanfn(void* parent_, const char* argval) {
struct arg_lit* parent = parent_;
int errorcode = 0;
if (parent->count < parent->hdr.maxcount)
parent->count++;
Expand All @@ -54,13 +56,15 @@ static int arg_lit_scanfn(struct arg_lit* parent, const char* argval) {
return errorcode;
}

static int arg_lit_checkfn(struct arg_lit* parent) {
static int arg_lit_checkfn(void* parent_) {
struct arg_lit* parent = parent_;
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}

static void arg_lit_errorfn(struct arg_lit* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
static void arg_lit_errorfn(void* parent_, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
struct arg_lit* parent = parent_;
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
Expand Down Expand Up @@ -106,10 +110,10 @@ struct arg_lit* arg_litn(const char* shortopts, const char* longopts, int mincou
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_lit_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_lit_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_lit_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_lit_errorfn;
result->hdr.resetfn = arg_lit_resetfn;
result->hdr.scanfn = arg_lit_scanfn;
result->hdr.checkfn = arg_lit_checkfn;
result->hdr.errorfn = arg_lit_errorfn;

/* init local variables */
result->count = 0;
Expand Down
20 changes: 12 additions & 8 deletions src/arg_rex.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,14 @@ struct privhdr {
int flags;
};

static void arg_rex_resetfn(struct arg_rex* parent) {
static void arg_rex_resetfn(void* parent_) {
struct arg_rex* parent = parent_;
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}

static int arg_rex_scanfn(struct arg_rex* parent, const char* argval) {
static int arg_rex_scanfn(void* parent_, const char* argval) {
struct arg_rex* parent = parent_;
int errorcode = 0;
const TRexChar* error = NULL;
TRex* rex = NULL;
Expand Down Expand Up @@ -161,7 +163,8 @@ static int arg_rex_scanfn(struct arg_rex* parent, const char* argval) {
return errorcode;
}

static int arg_rex_checkfn(struct arg_rex* parent) {
static int arg_rex_checkfn(void* parent_) {
struct arg_rex* parent = parent_;
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
#if 0
struct privhdr *priv = (struct privhdr*)parent->hdr.priv;
Expand All @@ -174,7 +177,8 @@ static int arg_rex_checkfn(struct arg_rex* parent) {
return errorcode;
}

static void arg_rex_errorfn(struct arg_rex* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
static void arg_rex_errorfn(void* parent_, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
struct arg_rex* parent = parent_;
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
Expand Down Expand Up @@ -255,10 +259,10 @@ struct arg_rex* arg_rexn(const char* shortopts,
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_rex_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_rex_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_rex_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_rex_errorfn;
result->hdr.resetfn = arg_rex_resetfn;
result->hdr.scanfn = arg_rex_scanfn;
result->hdr.checkfn = arg_rex_checkfn;
result->hdr.errorfn = arg_rex_errorfn;

/* store the arg_rex_priv struct immediately after the arg_rex struct */
result->hdr.priv = result + 1;
Expand Down
20 changes: 12 additions & 8 deletions src/arg_str.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@

#include <stdlib.h>

static void arg_str_resetfn(struct arg_str* parent) {
static void arg_str_resetfn(void* parent_) {
struct arg_str* parent = parent_;
int i;

ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
Expand All @@ -48,7 +49,8 @@ static void arg_str_resetfn(struct arg_str* parent) {
parent->count = 0;
}

static int arg_str_scanfn(struct arg_str* parent, const char* argval) {
static int arg_str_scanfn(void* parent_, const char* argval) {
struct arg_str* parent = parent_;
int errorcode = 0;

if (parent->count == parent->hdr.maxcount) {
Expand All @@ -67,14 +69,16 @@ static int arg_str_scanfn(struct arg_str* parent, const char* argval) {
return errorcode;
}

static int arg_str_checkfn(struct arg_str* parent) {
static int arg_str_checkfn(void* parent_) {
struct arg_str* parent = parent_;
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;

ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
return errorcode;
}

static void arg_str_errorfn(struct arg_str* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
static void arg_str_errorfn(void* parent_, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
struct arg_str* parent = parent_;
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
Expand Down Expand Up @@ -128,10 +132,10 @@ struct arg_str* arg_strn(const char* shortopts, const char* longopts, const char
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_str_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_str_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_str_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_str_errorfn;
result->hdr.resetfn = arg_str_resetfn;
result->hdr.scanfn = arg_str_scanfn;
result->hdr.checkfn = arg_str_checkfn;
result->hdr.errorfn = arg_str_errorfn;

/* store the sval[maxcount] array immediately after the arg_str struct */
result->sval = (const char**)(result + 1);
Expand Down