summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-04-21 21:15:24 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-04-21 21:15:24 -0700
commit368a4d05039d41eb31120f8624b9cf7037035d2e (patch)
tree9b064ccd97c5cdc0c0d946ab6efde6a9b48375fe
parentc2374487d235c08b71762d2ceb8645d18481c97f (diff)
downloadtxr-368a4d05039d41eb31120f8624b9cf7037035d2e.tar.gz
txr-368a4d05039d41eb31120f8624b9cf7037035d2e.tar.bz2
txr-368a4d05039d41eb31120f8624b9cf7037035d2e.zip
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.
-rw-r--r--glob.c2
-rw-r--r--parser.y4
-rw-r--r--socket.c12
-rw-r--r--stream.c3
-rw-r--r--sysif.c34
-rw-r--r--syslog.c12
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;
}