cherry-pick.FILE5_25-1-g7e60111.pr-479-check-the-format-length-modifiers.patch 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. Subject: PR/479: check the format length modifiers
  2. Origin: FILE5_25-1-g7e60111
  3. Upstream-Author: Christos Zoulas <christos@zoulas.com>
  4. Date: Wed Sep 16 18:21:26 2015 +0000
  5. --- a/src/apprentice.c
  6. +++ b/src/apprentice.c
  7. @@ -143,7 +143,7 @@
  8. private void apprentice_unmap(struct magic_map *);
  9. private int apprentice_compile(struct magic_set *, struct magic_map *,
  10. const char *);
  11. -private int check_format_type(const char *, int);
  12. +private int check_format_type(const char *, int, const char **);
  13. private int check_format(struct magic_set *, struct magic *);
  14. private int get_op(char);
  15. private int parse_mime(struct magic_set *, struct magic_entry *, const char *);
  16. @@ -2298,11 +2298,13 @@
  17. }
  18. private int
  19. -check_format_type(const char *ptr, int type)
  20. +check_format_type(const char *ptr, int type, const char **estr)
  21. {
  22. int quad = 0, h;
  23. + size_t len, cnt;
  24. if (*ptr == '\0') {
  25. /* Missing format string; bad */
  26. + *estr = "missing format spec";
  27. return -1;
  28. }
  29. @@ -2339,15 +2341,22 @@
  30. ptr++;
  31. if (*ptr == '.')
  32. ptr++;
  33. - while (isdigit((unsigned char)*ptr)) ptr++;
  34. +#define CHECKLEN() do { \
  35. + for (len = cnt = 0; isdigit((unsigned char)*ptr); ptr++, cnt++) \
  36. + len = len * 10 + (*ptr - '0'); \
  37. + if (cnt > 10 || len > 1024) \
  38. + goto toolong; \
  39. +} while (/*CONSTCOND*/0)
  40. +
  41. + CHECKLEN();
  42. if (*ptr == '.')
  43. ptr++;
  44. - while (isdigit((unsigned char)*ptr)) ptr++;
  45. + CHECKLEN();
  46. if (quad) {
  47. if (*ptr++ != 'l')
  48. - return -1;
  49. + goto invalid;
  50. if (*ptr++ != 'l')
  51. - return -1;
  52. + goto invalid;
  53. }
  54. switch (*ptr++) {
  55. @@ -2361,9 +2370,11 @@
  56. case 'o':
  57. case 'x':
  58. case 'X':
  59. - return h != 0 ? -1 : 0;
  60. + if (h == 0)
  61. + return 0;
  62. + /*FALLTHROUGH*/
  63. default:
  64. - return -1;
  65. + goto invalid;
  66. }
  67. /*
  68. @@ -2372,11 +2383,11 @@
  69. */
  70. case 'h':
  71. if (h-- <= 0)
  72. - return -1;
  73. + goto invalid;
  74. switch (*ptr++) {
  75. case 'h':
  76. if (h-- <= 0)
  77. - return -1;
  78. + goto invalid;
  79. switch (*ptr++) {
  80. case 'i':
  81. case 'd':
  82. @@ -2386,7 +2397,7 @@
  83. case 'X':
  84. return 0;
  85. default:
  86. - return -1;
  87. + goto invalid;
  88. }
  89. case 'i':
  90. case 'd':
  91. @@ -2394,13 +2405,17 @@
  92. case 'o':
  93. case 'x':
  94. case 'X':
  95. - return h != 0 ? -1 : 0;
  96. + if (h == 0)
  97. + return 0;
  98. + /*FALLTHROUGH*/
  99. default:
  100. - return -1;
  101. + goto invalid;
  102. }
  103. #endif
  104. case 'c':
  105. - return h != 2 ? -1 : 0;
  106. + if (h == 2)
  107. + return 0;
  108. + goto invalid;
  109. case 'i':
  110. case 'd':
  111. case 'u':
  112. @@ -2408,12 +2423,14 @@
  113. case 'x':
  114. case 'X':
  115. #ifdef STRICT_FORMAT
  116. - return h != 0 ? -1 : 0;
  117. + if (h == 0)
  118. + return 0;
  119. + /*FALLTHROUGH*/
  120. #else
  121. return 0;
  122. #endif
  123. default:
  124. - return -1;
  125. + goto invalid;
  126. }
  127. case FILE_FMT_FLOAT:
  128. @@ -2422,11 +2439,10 @@
  129. ptr++;
  130. if (*ptr == '.')
  131. ptr++;
  132. - while (isdigit((unsigned char)*ptr)) ptr++;
  133. + CHECKLEN();
  134. if (*ptr == '.')
  135. ptr++;
  136. - while (isdigit((unsigned char)*ptr)) ptr++;
  137. -
  138. + CHECKLEN();
  139. switch (*ptr++) {
  140. case 'e':
  141. case 'E':
  142. @@ -2437,7 +2453,7 @@
  143. return 0;
  144. default:
  145. - return -1;
  146. + goto invalid;
  147. }
  148. @@ -2456,14 +2472,17 @@
  149. case 's':
  150. return 0;
  151. default:
  152. - return -1;
  153. + goto invalid;
  154. }
  155. default:
  156. /* internal error */
  157. abort();
  158. }
  159. - /*NOTREACHED*/
  160. +invalid:
  161. + *estr = "not valid";
  162. +toolong:
  163. + *estr = "too long";
  164. return -1;
  165. }
  166. @@ -2475,6 +2494,7 @@
  167. check_format(struct magic_set *ms, struct magic *m)
  168. {
  169. char *ptr;
  170. + const char *estr;
  171. for (ptr = m->desc; *ptr; ptr++)
  172. if (*ptr == '%')
  173. @@ -2498,13 +2518,13 @@
  174. }
  175. ptr++;
  176. - if (check_format_type(ptr, m->type) == -1) {
  177. + if (check_format_type(ptr, m->type, &estr) == -1) {
  178. /*
  179. * TODO: this error message is unhelpful if the format
  180. * string is not one character long
  181. */
  182. - file_magwarn(ms, "Printf format `%c' is not valid for type "
  183. - "`%s' in description `%s'", *ptr ? *ptr : '?',
  184. + file_magwarn(ms, "Printf format is %s for type "
  185. + "`%s' in description `%s'", estr,
  186. file_names[m->type], m->desc);
  187. return -1;
  188. }