ref: 681cf749f874a0b1d9bb2da68e5928957b40216c
parent: 44f6f02e4214ac7d5fc775fdf44729ced8898cca
author: Ulrich Klauer <ulrich@chirlu.de>
date: Wed Jan 30 16:00:09 EST 2013
Fix (m)compand modifying their arguments The compand and mcompand effects modified their arguments while parsing them (via strtok(), which replaces characters by NUL). This caused two different problems: 1. For libSoX clients with hardcoded effect arguments given as C string literals, the program could crash during a call to sox_effect_options() since those literals may be in write-protected memory. Ryo Okamoto discovered this bug and provided code to reproduce it. 2. In SoX, a compand/mcompand effect in a restarted effects chain could see different arguments the second time it was created. E.g., sox -n -n trim 0 10 compand 0.2,0.5 -6 stats : restart failed at restart because the compand effect now saw "0.2" instead of "0.2,0.5" as its first argument, which is a syntax error. The fix duplicates the affected arguments and uses the copy for further processing.
--- a/ChangeLog
+++ b/ChangeLog
@@ -40,6 +40,7 @@
o Fix memory leaks in LADSPA effect. (Eric Wong)
o Fix hang in several effects (rate, tempo, and those based on
dft_filter) when processing long files. [3592482, 3594822] (MrMod)
+ o Prevent (m)compand from tampering with their arguments. (Ulrich Klauer)
Other bug fixes:
--- a/src/compand.c
+++ b/src/compand.c
@@ -58,6 +58,10 @@
ptrdiff_t delay_buf_index; /* Index into delay_buf */
ptrdiff_t delay_buf_cnt; /* No. of active entries in delay_buf */
int delay_buf_full; /* Shows buffer situation (important for drain) */
+
+ char *arg0; /* copies of arguments, so that they may be modified */
+ char *arg1;
+ char *arg2;
} priv_t;
static int getopts(sox_effect_t * effp, int argc, char * * argv)
@@ -71,8 +75,12 @@
if (argc < 2 || argc > 5)
return lsx_usage(effp);
+ l->arg0 = lsx_strdup(argv[0]);
+ l->arg1 = lsx_strdup(argv[1]);
+ l->arg2 = argc > 2 ? lsx_strdup(argv[2]) : NULL;
+
/* Start by checking the attack and decay rates */
- for (s = argv[0], commas = 0; *s; ++s) if (*s == ',') ++commas;
+ for (s = l->arg0, commas = 0; *s; ++s) if (*s == ',') ++commas;
if ((commas % 2) == 0) {
lsx_fail("there must be an even number of attack/decay parameters");
return SOX_EOF;
@@ -83,7 +91,7 @@
/* Now tokenise the rates string and set up these arrays. Keep
them in seconds at the moment: we don't know the sample rate yet. */
- for (i = 0, s = strtok(argv[0], ","); s != NULL; ++i) {
+ for (i = 0, s = strtok(l->arg0, ","); s != NULL; ++i) {
for (j = 0; j < 2; ++j) {
if (sscanf(s, "%lf %c", &l->channels[i].attack_times[j], &dummy) != 1) {
lsx_fail("syntax error trying to read attack/decay time");
@@ -96,7 +104,7 @@
}
}
- if (!lsx_compandt_parse(&l->transfer_fn, argv[1], argc>2 ? argv[2] : 0))
+ if (!lsx_compandt_parse(&l->transfer_fn, l->arg1, l->arg2))
return SOX_EOF;
/* Set the initial "volume" to be attibuted to the input channels.
@@ -269,6 +277,9 @@
lsx_compandt_kill(&l->transfer_fn);
free(l->channels);
+ free(l->arg0);
+ free(l->arg1);
+ free(l->arg2);
return SOX_SUCCESS;
}
--- a/src/mcompand.c
+++ b/src/mcompand.c
@@ -72,6 +72,8 @@
size_t band_buf_len;
size_t delay_buf_size;/* Size of delay_buf in samples */
comp_band_t *bands;
+
+ char *arg; /* copy of current argument */
} priv_t;
/*
@@ -174,7 +176,7 @@
/* how many bands? */
if (! (argc&1)) {
lsx_fail("mcompand accepts only an odd number of arguments:\argc"
- " mcompand quoted_compand_args [crossover_freq quoted_compand_args [...]");
+ " mcompand quoted_compand_args [crossover_freq quoted_compand_args [...]]");
return SOX_EOF;
}
c->nBands = (argc+1)>>1;
@@ -182,10 +184,13 @@
c->bands = lsx_calloc(c->nBands, sizeof(comp_band_t));
for (i=0;i<c->nBands;++i) {
- if (parse_subarg(argv[i<<1],subargv,&subargc) != SOX_SUCCESS)
+ c->arg = lsx_strdup(argv[i<<1]);
+ if (parse_subarg(c->arg,subargv,&subargc) != SOX_SUCCESS)
return SOX_EOF;
if (sox_mcompand_getopts_1(&c->bands[i], subargc, &subargv[0]) != SOX_SUCCESS)
return SOX_EOF;
+ free(c->arg);
+ c->arg = NULL;
if (i == (c->nBands-1))
c->bands[i].topfreq = 0;
else {
@@ -493,6 +498,7 @@
free(l->attackRate);
free(l->volume);
}
+ free(c->arg);
free(c->bands);
c->bands = NULL;