| 363 | */ |
| 364 | |
| 365 | static apr_status_t regsub_core(apr_pool_t *p, char **result, |
| 366 | struct ap_varbuf *vb, const char *input, |
| 367 | const char *source, apr_size_t nmatch, |
| 368 | ap_regmatch_t pmatch[], apr_size_t maxlen) |
| 369 | { |
| 370 | const char *src = input; |
| 371 | char *dst; |
| 372 | char c; |
| 373 | apr_size_t no; |
| 374 | apr_size_t len = 0; |
| 375 | |
| 376 | AP_DEBUG_ASSERT((result && p && !vb) || (vb && !p && !result)); |
| 377 | if (!source || nmatch>AP_MAX_REG_MATCH) |
| 378 | return APR_EINVAL; |
| 379 | if (!nmatch) { |
| 380 | len = strlen(src); |
| 381 | if (maxlen > 0 && len >= maxlen) |
| 382 | return APR_ENOMEM; |
| 383 | if (!vb) { |
| 384 | *result = apr_pstrmemdup(p, src, len); |
| 385 | return APR_SUCCESS; |
| 386 | } |
| 387 | else { |
| 388 | ap_varbuf_strmemcat(vb, src, len); |
| 389 | return APR_SUCCESS; |
| 390 | } |
| 391 | } |
| 392 | |
| 393 | /* First pass, find the size */ |
| 394 | while ((c = *src++) != '\0') { |
| 395 | if (c == '$' && apr_isdigit(*src)) |
| 396 | no = *src++ - '0'; |
| 397 | else |
| 398 | no = AP_MAX_REG_MATCH; |
| 399 | |
| 400 | if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */ |
| 401 | if (c == '\\' && *src) |
| 402 | src++; |
| 403 | len++; |
| 404 | } |
| 405 | else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) { |
| 406 | if (APR_SIZE_MAX - len <= pmatch[no].rm_eo - pmatch[no].rm_so) |
| 407 | return APR_ENOMEM; |
| 408 | len += pmatch[no].rm_eo - pmatch[no].rm_so; |
| 409 | } |
| 410 | |
| 411 | } |
| 412 | |
| 413 | if (len >= maxlen && maxlen > 0) |
| 414 | return APR_ENOMEM; |
| 415 | |
| 416 | if (!vb) { |
| 417 | *result = dst = apr_palloc(p, len + 1); |
| 418 | } |
| 419 | else { |
| 420 | if (vb->strlen == AP_VARBUF_UNKNOWN) |
| 421 | vb->strlen = strlen(vb->buf); |
| 422 | ap_varbuf_grow(vb, vb->strlen + len); |
no test coverage detected