From 368a4d05039d41eb31120f8624b9cf7037035d2e Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 21 Apr 2016 21:15:24 -0700 Subject: Strengthen against resource leaks upon exceptions. * glob.c (glob_wrap): Perform argument conversions that might throw before allocating UTF-8 string. * parser.y (text): In the action for SPACE, the lexeme is not needed so free($1) right away. If regex_compile were to throw an exception, that lexeme will leak. * socket.c (getaddrinfo_wrap): Harden against leakage of node_u8 and service_u8 strings with an unwind block. For instance, the hints structure could contain bad values which cause addrinfo_in to throw. * stream.c (make_string_byte_input_stream): Perform possibly throwing argument conversions before allocating resources. * sysif.c (mkdir_wrap, mknod_wrap, chmod_wrap, symlink_wrap, link_wrap, setenv_wrap, crypt_wrap): Likewise. * syslog.c (openlog_wrap, syslog_wrapv): Likewise. --- glob.c | 2 +- parser.y | 4 ++-- socket.c | 12 +++++++++--- stream.c | 3 ++- sysif.c | 34 +++++++++++++++++++++++----------- syslog.c | 12 +++++++----- 6 files changed, 44 insertions(+), 23 deletions(-) diff --git a/glob.c b/glob.c index 09151375..c5914b2a 100644 --- a/glob.c +++ b/glob.c @@ -66,9 +66,9 @@ static int errfunc_thunk(const char *errpath, int errcode) val glob_wrap(val pattern, val flags, val errfunc) { + cnum c_flags = c_num(default_arg(flags, zero)); char *pat_u8 = utf8_dup_to(c_str(pattern)); glob_t gl; - cnum c_flags = c_num(default_arg(flags, zero)); if (s_errfunc) { free(pat_u8); diff --git a/parser.y b/parser.y index dbaff205..f6ed9bf8 100644 --- a/parser.y +++ b/parser.y @@ -421,9 +421,9 @@ text : TEXT { $$ = rl(string_own($1), num(parser->lineno)); | SPACE { if ($1[0] == ' ' && $1[1] == 0) { val spaces = list(oneplus_s, chr(' '), nao); + free($1); $$ = regex_compile(spaces, nil); - rl($$, num(parser->lineno)); - free($1); } + rl($$, num(parser->lineno)); } else { $$ = rl(string_own($1), num(parser->lineno)); }} | regex { $$ = $1; diff --git a/socket.c b/socket.c index 5871632e..9b50959b 100644 --- a/socket.c +++ b/socket.c @@ -174,9 +174,11 @@ static val getaddrinfo_wrap(val node_in, val service_in, val hints_in) char *service_u8 = stringp(service) ? utf8_dup_to(c_str(service)) : 0; val node_num_p = integerp(node); val svc_num_p = integerp(service); - int res; + int res = 0; list_collect_decl (out, ptail); + uw_simple_catch_begin; + if (hints) { memset(&hints_ai, 0, sizeof hints_ai); addrinfo_in(&hints_ai, hints); @@ -184,8 +186,12 @@ static val getaddrinfo_wrap(val node_in, val service_in, val hints_in) res = getaddrinfo(node_u8, service_u8, phints, &alist); - free(node_u8); - free(service_u8); + uw_unwind { + free(node_u8); + free(service_u8); + } + + uw_catch_end; if (res == 0) { for (aiter = alist; aiter; aiter = aiter->ai_next) { diff --git a/stream.c b/stream.c index 3acf430a..39dbc18e 100644 --- a/stream.c +++ b/stream.c @@ -1690,9 +1690,10 @@ val make_string_byte_input_stream(val string) type_assert (stringp(string), (lit("~a is not a string"), string, nao)); { + const wchar_t *wstring = c_str(string); struct byte_input *bi = coerce(struct byte_input *, chk_malloc(sizeof *bi)); strm_base_init(&bi->a); - bi->buf = utf8_dup_to_buf(c_str(string), &bi->size, 0); + bi->buf = utf8_dup_to_buf(wstring, &bi->size, 0); bi->index = 0; return cobj(coerce(mem_t *, bi), stream_s, &byte_in_ops.cobj_ops); } diff --git a/sysif.c b/sysif.c index 70185a49..a3fdbb69 100644 --- a/sysif.c +++ b/sysif.c @@ -196,8 +196,9 @@ static val env_hash(void) #if HAVE_MKDIR static val mkdir_wrap(val path, val mode) { + cnum cmode = c_num(default_arg(mode, num_fast(0777))); char *u8path = utf8_dup_to(c_str(path)); - int err = mkdir(u8path, c_num(default_arg(mode, num_fast(0777)))); + int err = mkdir(u8path, cmode); free(u8path); if (err < 0) @@ -344,8 +345,10 @@ static val major_wrap(val dev) static val mknod_wrap(val path, val mode, val dev) { + cnum cmode = c_num(mode); + cnum cdev = c_num(default_arg(dev, zero)); char *u8path = utf8_dup_to(c_str(path)); - int err = mknod(u8path, c_num(mode), c_num(default_arg(dev, zero))); + int err = mknod(u8path, cmode, cdev); free(u8path); if (err < 0) @@ -368,8 +371,9 @@ static val mknod_wrap(val path, val mode, val dev) static val chmod_wrap(val path, val mode) { + cnum cmode = c_num(mode); char *u8path = utf8_dup_to(c_str(path)); - int err = chmod(u8path, c_num(mode)); + int err = chmod(u8path, cmode); free(u8path); if (err < 0) @@ -384,8 +388,10 @@ static val chmod_wrap(val path, val mode) static val symlink_wrap(val target, val to) { - char *u8target = utf8_dup_to(c_str(target)); - char *u8to = utf8_dup_to(c_str(to)); + const wchar_t *wtarget = c_str(target); + const wchar_t *wto = c_str(to); + char *u8target = utf8_dup_to(wtarget); + char *u8to = utf8_dup_to(wto); int err = symlink(u8target, u8to); free(u8target); free(u8to); @@ -397,8 +403,10 @@ static val symlink_wrap(val target, val to) static val link_wrap(val target, val to) { - char *u8target = utf8_dup_to(c_str(target)); - char *u8to = utf8_dup_to(c_str(to)); + const wchar_t *wtarget = c_str(target); + const wchar_t *wto = c_str(to); + char *u8target = utf8_dup_to(wtarget); + char *u8to = utf8_dup_to(wto); int err = link(u8target, u8to); free(u8target); free(u8to); @@ -708,9 +716,11 @@ val getenv_wrap(val name) static val setenv_wrap(val name, val value, val overwrite) { - char *nameu8 = utf8_dup_to(c_str(name)); - char *valu8 = value ? utf8_dup_to(c_str(value)) : 0; + const wchar_t *wname = c_str(name); + const wchar_t *wvalu = value ? c_str(value) : 0; int ovw = default_arg_strict(overwrite, t) != nil; + char *nameu8 = utf8_dup_to(wname); + char *valu8 = wvalu ? utf8_dup_to(wvalu) : 0; if (valu8) setenv(nameu8, valu8, ovw); else if (ovw) @@ -1117,8 +1127,10 @@ static val getgrnam_wrap(val wname) static val crypt_wrap(val wkey, val wsalt) { - char *key = utf8_dup_to(c_str(wkey)); - char *salt = utf8_dup_to(c_str(wsalt)); + const wchar_t *cwkey = c_str(wkey); + const wchar_t *cwsalt = c_str(wsalt); + char *key = utf8_dup_to(cwkey); + char *salt = utf8_dup_to(cwsalt); char *hash = crypt(key, salt); val whash = string_utf8(hash); free(key); diff --git a/syslog.c b/syslog.c index d5766f95..e0242729 100644 --- a/syslog.c +++ b/syslog.c @@ -91,13 +91,14 @@ void syslog_init(void) val openlog_wrap(val wident, val optmask, val facility) { static char *ident; + cnum coptmask = c_num(default_arg(optmask, zero)); + cnum cfacility = c_num(default_arg(facility, num_fast(LOG_USER))); char *old_ident = ident; - optmask = default_arg(optmask, zero); - facility = default_arg(facility, num_fast(LOG_USER)); - ident = utf8_dup_to(c_str(wident)); - openlog(ident, c_num(optmask), c_num(facility)); + + openlog(ident, coptmask, cfacility); + free(old_ident); return nil; @@ -111,8 +112,9 @@ val setlogmask_wrap(val mask) val syslog_wrapv(val prio, val fmt, struct args *args) { val text = formatv(nil, fmt, args); + cnum cprio = c_num(prio); char *u8text = utf8_dup_to(c_str(text)); - syslog(c_num(prio), "%s", u8text); + syslog(cprio, "%s", u8text); return nil; } -- cgit v1.2.3