ASF Bugzilla – Attachment 35885 Details for
Bug 62198
ap_rgetline_core can return without consuming a full line
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Handle AP_GETLINE_NOSPC_EOL flag in ap_rgetline_core()
AP_GETLINE_NOSPC_EOL-v2.patch (text/plain), 6.26 KB, created by
Yann Ylavic
on 2018-04-19 14:32:02 UTC
(
hide
)
Description:
Handle AP_GETLINE_NOSPC_EOL flag in ap_rgetline_core()
Filename:
MIME Type:
Creator:
Yann Ylavic
Created:
2018-04-19 14:32:02 UTC
Size:
6.26 KB
patch
obsolete
>Index: include/http_protocol.h >=================================================================== >--- include/http_protocol.h (revision 1829250) >+++ include/http_protocol.h (working copy) >@@ -631,7 +631,9 @@ AP_DECLARE(apr_status_t) ap_get_basic_auth_compone > AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri); > > #define AP_GETLINE_FOLD 1 /* Whether to merge continuation lines */ >-#define AP_GETLINE_CRLF 2 /*Whether line ends must be in the form CR LF */ >+#define AP_GETLINE_CRLF 2 /* Whether line ends must be in the form CR LF */ >+#define AP_GETLINE_NOSPC_EOL 4 /* Whether to consume up to and including the >+ end of line on APR_ENOSPC */ > > /** > * Get the next line of input for the request >Index: server/protocol.c >=================================================================== >--- server/protocol.c (revision 1829250) >+++ server/protocol.c (working copy) >@@ -224,6 +224,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s > int do_alloc = (*s == NULL), saw_eos = 0; > int fold = flags & AP_GETLINE_FOLD; > int crlf = flags & AP_GETLINE_CRLF; >+ int nospc_eol = flags & AP_GETLINE_NOSPC_EOL; >+ int saw_eol = 0, saw_nospc = 0; > > if (!n) { > /* Needs room for NUL byte at least */ >@@ -239,7 +241,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s > if (last_char) > *last_char = '\0'; > >- for (;;) { >+ do { > apr_brigade_cleanup(bb); > rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_GETLINE, > APR_BLOCK_READ, 0); >@@ -283,8 +285,52 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s > > /* Would this overrun our buffer? If so, we'll die. */ > if (n < bytes_handled + len) { >- rv = APR_ENOSPC; >- goto cleanup; >+ /* Before we die, let's fill the buffer up to its limit (i.e. >+ * fall through with the remaining length, if any), setting >+ * saw_eol on LF to stop the outer loop appropriately; we may >+ * come back here once the buffer is filled (no LF seen), and >+ * either be done at that time or continue to wait for LF here >+ * if nospc_eol is set. >+ * >+ * But there is also a corner cases which we want to address, >+ * namely if the buffer is overrun by the final LF only (i.e. >+ * the CR fits in); this is not really an overrun since we'll >+ * strip the CR finally (and use it for NUL byte), but anyway >+ * we have to handle the case so that it's not returned to the >+ * caller as part of the truncated line (it's not!). This is >+ * easier to consider that LF is out of counting and thus fall >+ * through with no error (saw_eol is set to 2 so that we later >+ * ignore LF handling already done here), while folding and >+ * nospc_eol logics continue to work (or fail) appropriately. >+ */ >+ saw_eol = (str[len - 1] == APR_ASCII_LF); >+ if (/* First time around */ >+ saw_eol && !saw_nospc >+ /* Single LF completing the buffered CR, */ >+ && ((len == 1 && ((*s)[bytes_handled - 1] == APR_ASCII_CR)) >+ /* or trailing CRLF overuns by LF only */ >+ || (len > 1 && str[len - 2] == APR_ASCII_CR >+ && n - bytes_handled + 1 == len))) { >+ /* In both cases *last_char is (to be) the CR stripped by >+ * later 'bytes_handled = last_char - *s'. >+ */ >+ saw_eol = 2; >+ } >+ else { >+ /* In any other case we'd lose data. */ >+ rv = APR_ENOSPC; >+ saw_nospc = 1; >+ } >+ len = n - bytes_handled; >+ if (!len) { >+ if (saw_eol) { >+ break; >+ } >+ if (nospc_eol) { >+ continue; >+ } >+ goto cleanup; >+ } > } > > /* Do we have to handle the allocation ourselves? */ >@@ -323,19 +369,29 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s > > /* If we got a full line of input, stop reading */ > if (last_char && (*last_char == APR_ASCII_LF)) { >- break; >+ saw_eol = 1; > } >+ } while (!saw_eol); >+ >+ if (rv != APR_SUCCESS) { >+ /* End of line after APR_ENOSPC above */ >+ goto cleanup; > } > > /* Now terminate the string at the end of the line; >- * if the last-but-one character is a CR, terminate there */ >- if (last_char > *s && last_char[-1] == APR_ASCII_CR) { >- last_char--; >+ * if the last-but-one character is a CR, terminate there. >+ * LF is handled above (not accounted) when saw_eol == 2, >+ * the last char is CR to terminate at still. >+ */ >+ if (saw_eol < 2) { >+ if (last_char > *s && last_char[-1] == APR_ASCII_CR) { >+ last_char--; >+ } >+ else if (crlf) { >+ rv = APR_EINVAL; >+ goto cleanup; >+ } > } >- else if (crlf) { >- rv = APR_EINVAL; >- goto cleanup; >- } > bytes_handled = last_char - *s; > > /* If we're folding, we have more work to do. >@@ -443,22 +499,22 @@ cleanup: > if (bytes_handled >= n) { > bytes_handled = n - 1; > } >+ >+ *read = bytes_handled; > if (*s) { > /* ensure the string is NUL terminated */ >- (*s)[bytes_handled] = '\0'; >- } >- *read = bytes_handled; >+ (*s)[*read] = '\0'; > >- if (rv != APR_SUCCESS) { >- return rv; >+ /* PR#43039: We shouldn't accept NULL bytes within the line */ >+ bytes_handled = strlen(*s); >+ if (bytes_handled < *read) { >+ *read = bytes_handled; >+ if (rv == APR_SUCCESS) { >+ rv = APR_EINVAL; >+ } >+ } > } >- >- /* PR#43039: We shouldn't accept NULL bytes within the line */ >- if (strlen(*s) < bytes_handled) { >- return APR_EINVAL; >- } >- >- return APR_SUCCESS; >+ return rv; > } > > #if APR_CHARSET_EBCDIC
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 62198
:
35863
| 35885