mirror of
https://github.com/moparisthebest/curl
synced 2024-11-17 06:55:02 -05:00
urlglob: improved error messages and column number on bad use
Introduce a convenience macro and keep of the column better so that it can point out the offending column better. Updated test 75 accordingly.
This commit is contained in:
parent
d6cda9e8ab
commit
9fa42beddc
@ -35,6 +35,9 @@ typedef enum {
|
|||||||
GLOB_ERROR = CURLE_URL_MALFORMAT
|
GLOB_ERROR = CURLE_URL_MALFORMAT
|
||||||
} GlobCode;
|
} GlobCode;
|
||||||
|
|
||||||
|
#define GLOBERROR(string, column, code) \
|
||||||
|
glob->error = string, glob->pos = column, code;
|
||||||
|
|
||||||
void glob_cleanup(URLGlob* glob);
|
void glob_cleanup(URLGlob* glob);
|
||||||
|
|
||||||
static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount)
|
static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount)
|
||||||
@ -49,15 +52,12 @@ static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount)
|
|||||||
|
|
||||||
pat->content.Set.elements = malloc(sizeof(char*));
|
pat->content.Set.elements = malloc(sizeof(char*));
|
||||||
|
|
||||||
if(!pat->content.Set.elements) {
|
if(!pat->content.Set.elements)
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
|
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||||
return GLOB_NO_MEM;
|
|
||||||
}
|
|
||||||
pat->content.Set.elements[0] = strdup(glob->glob_buffer);
|
pat->content.Set.elements[0] = strdup(glob->glob_buffer);
|
||||||
if(!pat->content.Set.elements[0]) {
|
if(!pat->content.Set.elements[0])
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
|
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||||
return GLOB_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLOB_OK;
|
return GLOB_OK;
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ static int multiply(unsigned long *amount, long with)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GlobCode glob_set(URLGlob *glob, char **patternp,
|
static GlobCode glob_set(URLGlob *glob, char **patternp,
|
||||||
size_t pos, unsigned long *amount,
|
size_t *posp, unsigned long *amount,
|
||||||
int globindex)
|
int globindex)
|
||||||
{
|
{
|
||||||
/* processes a set expression with the point behind the opening '{'
|
/* processes a set expression with the point behind the opening '{'
|
||||||
@ -87,6 +87,7 @@ static GlobCode glob_set(URLGlob *glob, char **patternp,
|
|||||||
char *buf = glob->glob_buffer;
|
char *buf = glob->glob_buffer;
|
||||||
char *pattern = *patternp;
|
char *pattern = *patternp;
|
||||||
char *opattern = pattern;
|
char *opattern = pattern;
|
||||||
|
size_t opos = *posp-1;
|
||||||
|
|
||||||
pat = &glob->pattern[glob->size];
|
pat = &glob->pattern[glob->size];
|
||||||
/* patterns 0,1,2,... correspond to size=1,3,5,... */
|
/* patterns 0,1,2,... correspond to size=1,3,5,... */
|
||||||
@ -99,27 +100,20 @@ static GlobCode glob_set(URLGlob *glob, char **patternp,
|
|||||||
while(!done) {
|
while(!done) {
|
||||||
switch (*pattern) {
|
switch (*pattern) {
|
||||||
case '\0': /* URL ended while set was still open */
|
case '\0': /* URL ended while set was still open */
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
return GLOBERROR("unmatched brace", opos, GLOB_ERROR);
|
||||||
"unmatched brace at pos %zu\n", pos);
|
|
||||||
return GLOB_ERROR;
|
|
||||||
|
|
||||||
case '{':
|
case '{':
|
||||||
case '[': /* no nested expressions at this time */
|
case '[': /* no nested expressions at this time */
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
return GLOBERROR("nested brace", *posp, GLOB_ERROR);
|
||||||
"nested braces not supported at pos %zu\n", pos);
|
|
||||||
return GLOB_ERROR;
|
|
||||||
|
|
||||||
case '}': /* set element completed */
|
case '}': /* set element completed */
|
||||||
if(opattern == pattern) {
|
if(opattern == pattern)
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
return GLOBERROR("empty string within braces", *posp, GLOB_ERROR);
|
||||||
"no string within braces at pos %zu\n", pos);
|
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
|
||||||
/* add 1 to size since it'll be incremented below */
|
/* add 1 to size since it'll be incremented below */
|
||||||
if(multiply(amount, pat->content.Set.size+1)) {
|
if(multiply(amount, pat->content.Set.size+1))
|
||||||
strcpy(glob->errormsg, "range overflow!\n");
|
return GLOBERROR("range overflow", 0, GLOB_ERROR);
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case ',':
|
case ',':
|
||||||
|
|
||||||
@ -127,27 +121,21 @@ static GlobCode glob_set(URLGlob *glob, char **patternp,
|
|||||||
if(pat->content.Set.elements) {
|
if(pat->content.Set.elements) {
|
||||||
char **new_arr = realloc(pat->content.Set.elements,
|
char **new_arr = realloc(pat->content.Set.elements,
|
||||||
(pat->content.Set.size + 1) * sizeof(char*));
|
(pat->content.Set.size + 1) * sizeof(char*));
|
||||||
if(!new_arr) {
|
if(!new_arr)
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
|
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||||
return GLOB_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
pat->content.Set.elements = new_arr;
|
pat->content.Set.elements = new_arr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pat->content.Set.elements = malloc(sizeof(char*));
|
pat->content.Set.elements = malloc(sizeof(char*));
|
||||||
|
|
||||||
if(!pat->content.Set.elements) {
|
if(!pat->content.Set.elements)
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
|
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||||
return GLOB_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
pat->content.Set.elements[pat->content.Set.size] =
|
pat->content.Set.elements[pat->content.Set.size] =
|
||||||
strdup(glob->glob_buffer);
|
strdup(glob->glob_buffer);
|
||||||
if(!pat->content.Set.elements[pat->content.Set.size]) {
|
if(!pat->content.Set.elements[pat->content.Set.size])
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
|
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||||
return GLOB_NO_MEM;
|
|
||||||
}
|
|
||||||
++pat->content.Set.size;
|
++pat->content.Set.size;
|
||||||
|
|
||||||
if(*pattern == '}') {
|
if(*pattern == '}') {
|
||||||
@ -158,23 +146,21 @@ static GlobCode glob_set(URLGlob *glob, char **patternp,
|
|||||||
|
|
||||||
buf = glob->glob_buffer;
|
buf = glob->glob_buffer;
|
||||||
++pattern;
|
++pattern;
|
||||||
++pos;
|
++(*posp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ']': /* illegal closing bracket */
|
case ']': /* illegal closing bracket */
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
return GLOBERROR("unexpected close bracket", *posp, GLOB_ERROR);
|
||||||
"illegal pattern at pos %zu\n", pos);
|
|
||||||
return GLOB_ERROR;
|
|
||||||
|
|
||||||
case '\\': /* escaped character, skip '\' */
|
case '\\': /* escaped character, skip '\' */
|
||||||
if(pattern[1]) {
|
if(pattern[1]) {
|
||||||
++pattern;
|
++pattern;
|
||||||
++pos;
|
++(*posp);
|
||||||
}
|
}
|
||||||
/* intentional fallthrough */
|
/* intentional fallthrough */
|
||||||
default:
|
default:
|
||||||
*buf++ = *pattern++; /* copy character to set element */
|
*buf++ = *pattern++; /* copy character to set element */
|
||||||
++pos;
|
++(*posp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +169,7 @@ static GlobCode glob_set(URLGlob *glob, char **patternp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GlobCode glob_range(URLGlob *glob, char **patternp,
|
static GlobCode glob_range(URLGlob *glob, char **patternp,
|
||||||
size_t pos, unsigned long *amount,
|
size_t *posp, unsigned long *amount,
|
||||||
int globindex)
|
int globindex)
|
||||||
{
|
{
|
||||||
/* processes a range expression with the point behind the opening '['
|
/* processes a range expression with the point behind the opening '['
|
||||||
@ -227,13 +213,12 @@ static GlobCode glob_range(URLGlob *glob, char **patternp,
|
|||||||
else
|
else
|
||||||
pattern+=3;
|
pattern+=3;
|
||||||
|
|
||||||
|
*posp += (pattern - *patternp);
|
||||||
|
|
||||||
if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
|
if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
|
||||||
(step < 0) ) {
|
(step < 0) )
|
||||||
/* the pattern is not well-formed */
|
/* the pattern is not well-formed */
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
return GLOBERROR("bad range", *posp, GLOB_ERROR);
|
||||||
"error: bad range specification after pos %zu\n", pos);
|
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if there was a ":[num]" thing, use that as step or else use 1 */
|
/* if there was a ":[num]" thing, use that as step or else use 1 */
|
||||||
pat->content.CharRange.step = step;
|
pat->content.CharRange.step = step;
|
||||||
@ -241,10 +226,8 @@ static GlobCode glob_range(URLGlob *glob, char **patternp,
|
|||||||
pat->content.CharRange.max_c = max_c;
|
pat->content.CharRange.max_c = max_c;
|
||||||
|
|
||||||
if(multiply(amount, (pat->content.CharRange.max_c -
|
if(multiply(amount, (pat->content.CharRange.max_c -
|
||||||
pat->content.CharRange.min_c + 1))) {
|
pat->content.CharRange.min_c + 1)))
|
||||||
strcpy(glob->errormsg, "range overflow!\n");
|
return GLOBERROR("range overflow", *posp, GLOB_ERROR);
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(ISDIGIT(*pattern)) {
|
else if(ISDIGIT(*pattern)) {
|
||||||
/* numeric range detected */
|
/* numeric range detected */
|
||||||
@ -295,12 +278,12 @@ static GlobCode glob_range(URLGlob *glob, char **patternp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!endp || (min_n > max_n) || (step_n > (max_n - min_n))) {
|
*posp += (pattern - *patternp);
|
||||||
|
|
||||||
|
if(!endp || (min_n > max_n) || (step_n > (max_n - min_n)))
|
||||||
/* the pattern is not well-formed */
|
/* the pattern is not well-formed */
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
return GLOBERROR("bad range", *posp, GLOB_ERROR);
|
||||||
"error: bad range specification after pos %zu\n", pos);
|
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
|
||||||
/* typecasting to ints are fine here since we make sure above that we
|
/* typecasting to ints are fine here since we make sure above that we
|
||||||
are within 31 bits */
|
are within 31 bits */
|
||||||
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
|
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
|
||||||
@ -308,16 +291,11 @@ static GlobCode glob_range(URLGlob *glob, char **patternp,
|
|||||||
pat->content.NumRange.step = step_n;
|
pat->content.NumRange.step = step_n;
|
||||||
|
|
||||||
if(multiply(amount, (pat->content.NumRange.max_n -
|
if(multiply(amount, (pat->content.NumRange.max_n -
|
||||||
pat->content.NumRange.min_n + 1))) {
|
pat->content.NumRange.min_n + 1)))
|
||||||
strcpy(glob->errormsg, "range overflow!\n");
|
return GLOBERROR("range overflow", *posp, GLOB_ERROR);
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
|
||||||
"illegal character in range specification at pos %zu\n", pos);
|
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return GLOBERROR("bad range specification", *posp, GLOB_ERROR);
|
||||||
|
|
||||||
*patternp = pattern;
|
*patternp = pattern;
|
||||||
return GLOB_OK;
|
return GLOB_OK;
|
||||||
@ -336,11 +314,8 @@ static GlobCode glob_parse(URLGlob *glob, char *pattern,
|
|||||||
while(*pattern && !res) {
|
while(*pattern && !res) {
|
||||||
int sublen = 0;
|
int sublen = 0;
|
||||||
while(*pattern && *pattern != '{' && *pattern != '[') {
|
while(*pattern && *pattern != '{' && *pattern != '[') {
|
||||||
if(*pattern == '}' || *pattern == ']') {
|
if(*pattern == '}' || *pattern == ']')
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
return GLOBERROR("unmatched close brace/bracket", pos, GLOB_ERROR);
|
||||||
"unmatched close brace/bracket at pos %zu\n", pos);
|
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* only allow \ to escape known "special letters" */
|
/* only allow \ to escape known "special letters" */
|
||||||
if(*pattern == '\\' &&
|
if(*pattern == '\\' &&
|
||||||
@ -371,23 +346,21 @@ static GlobCode glob_parse(URLGlob *glob, char *pattern,
|
|||||||
case '{':
|
case '{':
|
||||||
/* process set pattern */
|
/* process set pattern */
|
||||||
pattern++;
|
pattern++;
|
||||||
res = glob_set(glob, &pattern, ++pos, amount, globindex++);
|
pos++;
|
||||||
|
res = glob_set(glob, &pattern, &pos, amount, globindex++);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
/* process range pattern */
|
/* process range pattern */
|
||||||
pattern++;
|
pattern++;
|
||||||
res = glob_range(glob, &pattern, ++pos, amount, globindex++);
|
pos++;
|
||||||
|
res = glob_range(glob, &pattern, &pos, amount, globindex++);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(++glob->size > GLOB_PATTERN_NUM) {
|
if(++glob->size > GLOB_PATTERN_NUM)
|
||||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
return GLOBERROR("too many globs", pos, GLOB_ERROR);
|
||||||
"too many globs used\n");
|
|
||||||
return GLOB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -421,9 +394,19 @@ int glob_url(URLGlob** glob, char* url, unsigned long *urlnum, FILE *error)
|
|||||||
if(!res)
|
if(!res)
|
||||||
*urlnum = amount;
|
*urlnum = amount;
|
||||||
else {
|
else {
|
||||||
if(error && glob_expand->errormsg[0]) {
|
if(error && glob_expand->error) {
|
||||||
|
char text[128];
|
||||||
|
const char *t;
|
||||||
|
if(glob_expand->pos) {
|
||||||
|
snprintf(text, sizeof(text), "%s in column %zu", glob_expand->error,
|
||||||
|
glob_expand->pos);
|
||||||
|
t = text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
t = glob_expand->error;
|
||||||
|
|
||||||
/* send error description to the error-stream */
|
/* send error description to the error-stream */
|
||||||
fprintf(error, "curl: (%d) [globbing] %s", res, glob_expand->errormsg);
|
fprintf(error, "curl: (%d) [globbing] %s\n", res, t);
|
||||||
}
|
}
|
||||||
/* it failed, we cleanup */
|
/* it failed, we cleanup */
|
||||||
glob_cleanup(glob_expand);
|
glob_cleanup(glob_expand);
|
||||||
|
@ -64,7 +64,8 @@ typedef struct {
|
|||||||
size_t urllen;
|
size_t urllen;
|
||||||
char *glob_buffer;
|
char *glob_buffer;
|
||||||
char beenhere;
|
char beenhere;
|
||||||
char errormsg[80]; /* error message buffer */
|
const char *error; /* error message */
|
||||||
|
size_t pos; /* column position of error or 0 */
|
||||||
} URLGlob;
|
} URLGlob;
|
||||||
|
|
||||||
int glob_url(URLGlob**, char*, unsigned long *, FILE *);
|
int glob_url(URLGlob**, char*, unsigned long *, FILE *);
|
||||||
|
@ -24,7 +24,7 @@ http
|
|||||||
HTTP, urlglob retrieval with bad range
|
HTTP, urlglob retrieval with bad range
|
||||||
</name>
|
</name>
|
||||||
<command option="no-output">
|
<command option="no-output">
|
||||||
"http://%HOSTIP:%HTTPPORT/[2-1]" -o "log/weee#1.dump" --stderr -
|
"http://a-site-never-accessed.example.org/[2-1]" -o "log/weee#1.dump" --stderr -
|
||||||
</command>
|
</command>
|
||||||
# The error message on stdout implicitly depends on the length of the
|
# The error message on stdout implicitly depends on the length of the
|
||||||
# URL, so refuse to run if the length is unexpected.
|
# URL, so refuse to run if the length is unexpected.
|
||||||
@ -43,7 +43,7 @@ perl %SRCDIR/libtest/test75.pl http://%HOSTIP:%HTTPPORT/ 22
|
|||||||
3
|
3
|
||||||
</errorcode>
|
</errorcode>
|
||||||
<stdout mode="text">
|
<stdout mode="text">
|
||||||
curl: (3) [globbing] error: bad range specification after pos 24
|
curl: (3) [globbing] bad range in column 47
|
||||||
</stdout>
|
</stdout>
|
||||||
</verify>
|
</verify>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
Loading…
Reference in New Issue
Block a user