|
| 1 | +From 308d60fecf09870b99fabdf60e86115302b4506a Mon Sep 17 00:00:00 2001 |
| 2 | +From: Sebastian Pipping < [email protected]> |
| 3 | +Date: Thu, 30 Dec 2021 22:46:03 +0100 |
| 4 | +Subject: [PATCH] lib: Prevent integer overflow at multiple places |
| 5 | + (CVE-2022-22822 to CVE-2022-22827) |
| 6 | + |
| 7 | +The involved functions are: |
| 8 | +- addBinding (CVE-2022-22822) |
| 9 | +- build_model (CVE-2022-22823) |
| 10 | +- defineAttribute (CVE-2022-22824) |
| 11 | +- lookup (CVE-2022-22825) |
| 12 | +- nextScaffoldPart (CVE-2022-22826) |
| 13 | +- storeAtts (CVE-2022-22827) |
| 14 | +--- |
| 15 | + lib/xmlparse.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++- |
| 16 | + 1 file changed, 151 insertions(+), 2 deletions(-) |
| 17 | + |
| 18 | +diff --git a/lib/xmlparse.c b/lib/xmlparse.c |
| 19 | +index 5ba56ea..5eef168 100644 |
| 20 | +--- a/lib/xmlparse.c |
| 21 | ++++ b/lib/xmlparse.c |
| 22 | +@@ -3260,13 +3260,38 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, |
| 23 | + |
| 24 | + /* get the attributes from the tokenizer */ |
| 25 | + n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts); |
| 26 | ++ |
| 27 | ++ /* Detect and prevent integer overflow */ |
| 28 | ++ if (n > INT_MAX - nDefaultAtts) { |
| 29 | ++ return XML_ERROR_NO_MEMORY; |
| 30 | ++ } |
| 31 | ++ |
| 32 | + if (n + nDefaultAtts > parser->m_attsSize) { |
| 33 | + int oldAttsSize = parser->m_attsSize; |
| 34 | + ATTRIBUTE *temp; |
| 35 | + #ifdef XML_ATTR_INFO |
| 36 | + XML_AttrInfo *temp2; |
| 37 | + #endif |
| 38 | ++ |
| 39 | ++ /* Detect and prevent integer overflow */ |
| 40 | ++ if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE) |
| 41 | ++ || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) { |
| 42 | ++ return XML_ERROR_NO_MEMORY; |
| 43 | ++ } |
| 44 | ++ |
| 45 | + parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; |
| 46 | ++ |
| 47 | ++ /* Detect and prevent integer overflow. |
| 48 | ++ * The preprocessor guard addresses the "always false" warning |
| 49 | ++ * from -Wtype-limits on platforms where |
| 50 | ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ |
| 51 | ++#if UINT_MAX >= SIZE_MAX |
| 52 | ++ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) { |
| 53 | ++ parser->m_attsSize = oldAttsSize; |
| 54 | ++ return XML_ERROR_NO_MEMORY; |
| 55 | ++ } |
| 56 | ++#endif |
| 57 | ++ |
| 58 | + temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, |
| 59 | + parser->m_attsSize * sizeof(ATTRIBUTE)); |
| 60 | + if (temp == NULL) { |
| 61 | +@@ -3275,6 +3300,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, |
| 62 | + } |
| 63 | + parser->m_atts = temp; |
| 64 | + #ifdef XML_ATTR_INFO |
| 65 | ++ /* Detect and prevent integer overflow. |
| 66 | ++ * The preprocessor guard addresses the "always false" warning |
| 67 | ++ * from -Wtype-limits on platforms where |
| 68 | ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ |
| 69 | ++# if UINT_MAX >= SIZE_MAX |
| 70 | ++ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) { |
| 71 | ++ parser->m_attsSize = oldAttsSize; |
| 72 | ++ return XML_ERROR_NO_MEMORY; |
| 73 | ++ } |
| 74 | ++# endif |
| 75 | ++ |
| 76 | + temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, |
| 77 | + parser->m_attsSize * sizeof(XML_AttrInfo)); |
| 78 | + if (temp2 == NULL) { |
| 79 | +@@ -3582,9 +3618,31 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, |
| 80 | + tagNamePtr->prefixLen = prefixLen; |
| 81 | + for (i = 0; localPart[i++];) |
| 82 | + ; /* i includes null terminator */ |
| 83 | ++ |
| 84 | ++ /* Detect and prevent integer overflow */ |
| 85 | ++ if (binding->uriLen > INT_MAX - prefixLen |
| 86 | ++ || i > INT_MAX - (binding->uriLen + prefixLen)) { |
| 87 | ++ return XML_ERROR_NO_MEMORY; |
| 88 | ++ } |
| 89 | ++ |
| 90 | + n = i + binding->uriLen + prefixLen; |
| 91 | + if (n > binding->uriAlloc) { |
| 92 | + TAG *p; |
| 93 | ++ |
| 94 | ++ /* Detect and prevent integer overflow */ |
| 95 | ++ if (n > INT_MAX - EXPAND_SPARE) { |
| 96 | ++ return XML_ERROR_NO_MEMORY; |
| 97 | ++ } |
| 98 | ++ /* Detect and prevent integer overflow. |
| 99 | ++ * The preprocessor guard addresses the "always false" warning |
| 100 | ++ * from -Wtype-limits on platforms where |
| 101 | ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ |
| 102 | ++#if UINT_MAX >= SIZE_MAX |
| 103 | ++ if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { |
| 104 | ++ return XML_ERROR_NO_MEMORY; |
| 105 | ++ } |
| 106 | ++#endif |
| 107 | ++ |
| 108 | + uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char)); |
| 109 | + if (! uri) |
| 110 | + return XML_ERROR_NO_MEMORY; |
| 111 | +@@ -3680,6 +3738,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, |
| 112 | + if (parser->m_freeBindingList) { |
| 113 | + b = parser->m_freeBindingList; |
| 114 | + if (len > b->uriAlloc) { |
| 115 | ++ /* Detect and prevent integer overflow */ |
| 116 | ++ if (len > INT_MAX - EXPAND_SPARE) { |
| 117 | ++ return XML_ERROR_NO_MEMORY; |
| 118 | ++ } |
| 119 | ++ |
| 120 | ++ /* Detect and prevent integer overflow. |
| 121 | ++ * The preprocessor guard addresses the "always false" warning |
| 122 | ++ * from -Wtype-limits on platforms where |
| 123 | ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ |
| 124 | ++#if UINT_MAX >= SIZE_MAX |
| 125 | ++ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { |
| 126 | ++ return XML_ERROR_NO_MEMORY; |
| 127 | ++ } |
| 128 | ++#endif |
| 129 | ++ |
| 130 | + XML_Char *temp = (XML_Char *)REALLOC( |
| 131 | + parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); |
| 132 | + if (temp == NULL) |
| 133 | +@@ -3692,6 +3765,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, |
| 134 | + b = (BINDING *)MALLOC(parser, sizeof(BINDING)); |
| 135 | + if (! b) |
| 136 | + return XML_ERROR_NO_MEMORY; |
| 137 | ++ |
| 138 | ++ /* Detect and prevent integer overflow */ |
| 139 | ++ if (len > INT_MAX - EXPAND_SPARE) { |
| 140 | ++ return XML_ERROR_NO_MEMORY; |
| 141 | ++ } |
| 142 | ++ /* Detect and prevent integer overflow. |
| 143 | ++ * The preprocessor guard addresses the "always false" warning |
| 144 | ++ * from -Wtype-limits on platforms where |
| 145 | ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ |
| 146 | ++#if UINT_MAX >= SIZE_MAX |
| 147 | ++ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { |
| 148 | ++ return XML_ERROR_NO_MEMORY; |
| 149 | ++ } |
| 150 | ++#endif |
| 151 | ++ |
| 152 | + b->uri |
| 153 | + = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); |
| 154 | + if (! b->uri) { |
| 155 | +@@ -6098,7 +6186,24 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, |
| 156 | + } |
| 157 | + } else { |
| 158 | + DEFAULT_ATTRIBUTE *temp; |
| 159 | ++ |
| 160 | ++ /* Detect and prevent integer overflow */ |
| 161 | ++ if (type->allocDefaultAtts > INT_MAX / 2) { |
| 162 | ++ return 0; |
| 163 | ++ } |
| 164 | ++ |
| 165 | + int count = type->allocDefaultAtts * 2; |
| 166 | ++ |
| 167 | ++ /* Detect and prevent integer overflow. |
| 168 | ++ * The preprocessor guard addresses the "always false" warning |
| 169 | ++ * from -Wtype-limits on platforms where |
| 170 | ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ |
| 171 | ++#if UINT_MAX >= SIZE_MAX |
| 172 | ++ if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) { |
| 173 | ++ return 0; |
| 174 | ++ } |
| 175 | ++#endif |
| 176 | ++ |
| 177 | + temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts, |
| 178 | + (count * sizeof(DEFAULT_ATTRIBUTE))); |
| 179 | + if (temp == NULL) |
| 180 | +@@ -6749,8 +6854,20 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { |
| 181 | + /* check for overflow (table is half full) */ |
| 182 | + if (table->used >> (table->power - 1)) { |
| 183 | + unsigned char newPower = table->power + 1; |
| 184 | ++ |
| 185 | ++ /* Detect and prevent invalid shift */ |
| 186 | ++ if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) { |
| 187 | ++ return NULL; |
| 188 | ++ } |
| 189 | ++ |
| 190 | + size_t newSize = (size_t)1 << newPower; |
| 191 | + unsigned long newMask = (unsigned long)newSize - 1; |
| 192 | ++ |
| 193 | ++ /* Detect and prevent integer overflow */ |
| 194 | ++ if (newSize > (size_t)(-1) / sizeof(NAMED *)) { |
| 195 | ++ return NULL; |
| 196 | ++ } |
| 197 | ++ |
| 198 | + size_t tsize = newSize * sizeof(NAMED *); |
| 199 | + NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); |
| 200 | + if (! newV) |
| 201 | +@@ -7100,6 +7217,20 @@ nextScaffoldPart(XML_Parser parser) { |
| 202 | + if (dtd->scaffCount >= dtd->scaffSize) { |
| 203 | + CONTENT_SCAFFOLD *temp; |
| 204 | + if (dtd->scaffold) { |
| 205 | ++ /* Detect and prevent integer overflow */ |
| 206 | ++ if (dtd->scaffSize > UINT_MAX / 2u) { |
| 207 | ++ return -1; |
| 208 | ++ } |
| 209 | ++ /* Detect and prevent integer overflow. |
| 210 | ++ * The preprocessor guard addresses the "always false" warning |
| 211 | ++ * from -Wtype-limits on platforms where |
| 212 | ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ |
| 213 | ++#if UINT_MAX >= SIZE_MAX |
| 214 | ++ if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) { |
| 215 | ++ return -1; |
| 216 | ++ } |
| 217 | ++#endif |
| 218 | ++ |
| 219 | + temp = (CONTENT_SCAFFOLD *)REALLOC( |
| 220 | + parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); |
| 221 | + if (temp == NULL) |
| 222 | +@@ -7169,8 +7300,26 @@ build_model(XML_Parser parser) { |
| 223 | + XML_Content *ret; |
| 224 | + XML_Content *cpos; |
| 225 | + XML_Char *str; |
| 226 | +- int allocsize = (dtd->scaffCount * sizeof(XML_Content) |
| 227 | +- + (dtd->contentStringLen * sizeof(XML_Char))); |
| 228 | ++ |
| 229 | ++ /* Detect and prevent integer overflow. |
| 230 | ++ * The preprocessor guard addresses the "always false" warning |
| 231 | ++ * from -Wtype-limits on platforms where |
| 232 | ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ |
| 233 | ++#if UINT_MAX >= SIZE_MAX |
| 234 | ++ if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) { |
| 235 | ++ return NULL; |
| 236 | ++ } |
| 237 | ++ if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) { |
| 238 | ++ return NULL; |
| 239 | ++ } |
| 240 | ++#endif |
| 241 | ++ if (dtd->scaffCount * sizeof(XML_Content) |
| 242 | ++ > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) { |
| 243 | ++ return NULL; |
| 244 | ++ } |
| 245 | ++ |
| 246 | ++ const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content) |
| 247 | ++ + (dtd->contentStringLen * sizeof(XML_Char))); |
| 248 | + |
| 249 | + ret = (XML_Content *)MALLOC(parser, allocsize); |
| 250 | + if (! ret) |
| 251 | +-- |
| 252 | +2.17.1 |
| 253 | + |
0 commit comments