| 1263 | */ |
| 1264 | |
| 1265 | ParseResult |
| 1266 | url_parse_internet(HdrHeap *heap, URLImpl *url, const char **start, char const *end, bool copy_strings_p, |
| 1267 | bool verify_host_characters) |
| 1268 | { |
| 1269 | const char *cur = *start; |
| 1270 | const char *base; // Base for host/port field. |
| 1271 | const char *bracket = nullptr; // marker for open bracket, if any. |
| 1272 | swoc::TextView user, passw, host, port; |
| 1273 | static size_t const MAX_COLON = 8; // max # of valid colons. |
| 1274 | size_t n_colon = 0; |
| 1275 | const char *last_colon = nullptr; // pointer to last colon seen. |
| 1276 | |
| 1277 | // Do a quick check for "://" |
| 1278 | if (end - cur > 3 && (((':' ^ *cur) | ('/' ^ cur[1]) | ('/' ^ cur[2])) == 0)) { |
| 1279 | cur += 3; |
| 1280 | } else if (':' == *cur && (++cur >= end || ('/' == *cur && (++cur >= end || ('/' == *cur && ++cur >= end))))) { |
| 1281 | return PARSE_RESULT_ERROR; |
| 1282 | } |
| 1283 | |
| 1284 | base = cur; |
| 1285 | // skipped leading stuff, start real parsing. |
| 1286 | while (cur < end) { |
| 1287 | // Note: Each case is responsible for incrementing @a cur if |
| 1288 | // appropriate! |
| 1289 | switch (*cur) { |
| 1290 | case ']': // address close |
| 1291 | if (nullptr == bracket || n_colon >= MAX_COLON) { |
| 1292 | return PARSE_RESULT_ERROR; |
| 1293 | } |
| 1294 | ++cur; |
| 1295 | /* We keep the brackets because there are too many other places |
| 1296 | that depend on them and it's too painful to keep track if |
| 1297 | they should be used. I thought about being clever with |
| 1298 | stripping brackets from non-IPv6 content but that gets ugly |
| 1299 | as well. Just not worth it. |
| 1300 | */ |
| 1301 | host.assign(bracket, cur); |
| 1302 | // Spec requires This constitute the entire host so the next |
| 1303 | // character must be missing (EOS), slash, or colon. |
| 1304 | if (cur >= end || '/' == *cur) { // done which is OK |
| 1305 | last_colon = nullptr; |
| 1306 | break; |
| 1307 | } else if (':' != *cur) { // otherwise it must be a colon |
| 1308 | return PARSE_RESULT_ERROR; |
| 1309 | } |
| 1310 | /* We want to prevent more than 1 colon following so we set @a |
| 1311 | n_colon appropriately. |
| 1312 | */ |
| 1313 | n_colon = MAX_COLON - 1; |
| 1314 | // FALL THROUGH |
| 1315 | case ':': // track colons, fail if too many. |
| 1316 | if (++n_colon > MAX_COLON) { |
| 1317 | return PARSE_RESULT_ERROR; |
| 1318 | } |
| 1319 | last_colon = cur; |
| 1320 | ++cur; |
| 1321 | break; |
| 1322 | case '@': // user/password marker. |
no test coverage detected