123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- Subject: PR/479: check the format length modifiers
- Origin: FILE5_25-1-g7e60111
- Upstream-Author: Christos Zoulas <christos@zoulas.com>
- Date: Wed Sep 16 18:21:26 2015 +0000
- --- a/src/apprentice.c
- +++ b/src/apprentice.c
- @@ -143,7 +143,7 @@
- private void apprentice_unmap(struct magic_map *);
- private int apprentice_compile(struct magic_set *, struct magic_map *,
- const char *);
- -private int check_format_type(const char *, int);
- +private int check_format_type(const char *, int, const char **);
- private int check_format(struct magic_set *, struct magic *);
- private int get_op(char);
- private int parse_mime(struct magic_set *, struct magic_entry *, const char *);
- @@ -2298,11 +2298,13 @@
- }
-
- private int
- -check_format_type(const char *ptr, int type)
- +check_format_type(const char *ptr, int type, const char **estr)
- {
- int quad = 0, h;
- + size_t len, cnt;
- if (*ptr == '\0') {
- /* Missing format string; bad */
- + *estr = "missing format spec";
- return -1;
- }
-
- @@ -2339,15 +2341,22 @@
- ptr++;
- if (*ptr == '.')
- ptr++;
- - while (isdigit((unsigned char)*ptr)) ptr++;
- +#define CHECKLEN() do { \
- + for (len = cnt = 0; isdigit((unsigned char)*ptr); ptr++, cnt++) \
- + len = len * 10 + (*ptr - '0'); \
- + if (cnt > 10 || len > 1024) \
- + goto toolong; \
- +} while (/*CONSTCOND*/0)
- +
- + CHECKLEN();
- if (*ptr == '.')
- ptr++;
- - while (isdigit((unsigned char)*ptr)) ptr++;
- + CHECKLEN();
- if (quad) {
- if (*ptr++ != 'l')
- - return -1;
- + goto invalid;
- if (*ptr++ != 'l')
- - return -1;
- + goto invalid;
- }
-
- switch (*ptr++) {
- @@ -2361,9 +2370,11 @@
- case 'o':
- case 'x':
- case 'X':
- - return h != 0 ? -1 : 0;
- + if (h == 0)
- + return 0;
- + /*FALLTHROUGH*/
- default:
- - return -1;
- + goto invalid;
- }
-
- /*
- @@ -2372,11 +2383,11 @@
- */
- case 'h':
- if (h-- <= 0)
- - return -1;
- + goto invalid;
- switch (*ptr++) {
- case 'h':
- if (h-- <= 0)
- - return -1;
- + goto invalid;
- switch (*ptr++) {
- case 'i':
- case 'd':
- @@ -2386,7 +2397,7 @@
- case 'X':
- return 0;
- default:
- - return -1;
- + goto invalid;
- }
- case 'i':
- case 'd':
- @@ -2394,13 +2405,17 @@
- case 'o':
- case 'x':
- case 'X':
- - return h != 0 ? -1 : 0;
- + if (h == 0)
- + return 0;
- + /*FALLTHROUGH*/
- default:
- - return -1;
- + goto invalid;
- }
- #endif
- case 'c':
- - return h != 2 ? -1 : 0;
- + if (h == 2)
- + return 0;
- + goto invalid;
- case 'i':
- case 'd':
- case 'u':
- @@ -2408,12 +2423,14 @@
- case 'x':
- case 'X':
- #ifdef STRICT_FORMAT
- - return h != 0 ? -1 : 0;
- + if (h == 0)
- + return 0;
- + /*FALLTHROUGH*/
- #else
- return 0;
- #endif
- default:
- - return -1;
- + goto invalid;
- }
-
- case FILE_FMT_FLOAT:
- @@ -2422,11 +2439,10 @@
- ptr++;
- if (*ptr == '.')
- ptr++;
- - while (isdigit((unsigned char)*ptr)) ptr++;
- + CHECKLEN();
- if (*ptr == '.')
- ptr++;
- - while (isdigit((unsigned char)*ptr)) ptr++;
- -
- + CHECKLEN();
- switch (*ptr++) {
- case 'e':
- case 'E':
- @@ -2437,7 +2453,7 @@
- return 0;
-
- default:
- - return -1;
- + goto invalid;
- }
-
-
- @@ -2456,14 +2472,17 @@
- case 's':
- return 0;
- default:
- - return -1;
- + goto invalid;
- }
-
- default:
- /* internal error */
- abort();
- }
- - /*NOTREACHED*/
- +invalid:
- + *estr = "not valid";
- +toolong:
- + *estr = "too long";
- return -1;
- }
-
- @@ -2475,6 +2494,7 @@
- check_format(struct magic_set *ms, struct magic *m)
- {
- char *ptr;
- + const char *estr;
-
- for (ptr = m->desc; *ptr; ptr++)
- if (*ptr == '%')
- @@ -2498,13 +2518,13 @@
- }
-
- ptr++;
- - if (check_format_type(ptr, m->type) == -1) {
- + if (check_format_type(ptr, m->type, &estr) == -1) {
- /*
- * TODO: this error message is unhelpful if the format
- * string is not one character long
- */
- - file_magwarn(ms, "Printf format `%c' is not valid for type "
- - "`%s' in description `%s'", *ptr ? *ptr : '?',
- + file_magwarn(ms, "Printf format is %s for type "
- + "`%s' in description `%s'", estr,
- file_names[m->type], m->desc);
- return -1;
- }
|