Index: httpd-2.4.10/server/protocol.c
===================================================================
--- httpd-2.4.10.orig/server/protocol.c	2018-03-29 11:09:44.392672821 +0200
+++ httpd-2.4.10/server/protocol.c	2018-03-29 11:33:17.695075259 +0200
@@ -216,6 +216,11 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
     char *pos, *last_char = *s;
     int do_alloc = (*s == NULL), saw_eos = 0;
 
+    if (!n) {
+        /* Needs room for NUL byte at least */
+        return APR_BADARG;
+    }
+
     /*
      * Initialize last_char as otherwise a random value will be compared
      * against APR_ASCII_LF at the end of the loop if bb only contains
@@ -229,12 +234,13 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
         rv = ap_get_brigade(r->input_filters, bb, AP_MODE_GETLINE,
                             APR_BLOCK_READ, 0);
         if (rv != APR_SUCCESS) {
-            return rv;
+            goto cleanup;
         }
 
         /* Something horribly wrong happened.  Someone didn't block! */
         if (APR_BRIGADE_EMPTY(bb)) {
-            return APR_EGENERAL;
+            rv = APR_EGENERAL;
+            goto cleanup;
         }
 
         for (e = APR_BRIGADE_FIRST(bb);
@@ -252,7 +258,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
 
             rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
             if (rv != APR_SUCCESS) {
-                return rv;
+                goto cleanup;
             }
 
             if (len == 0) {
@@ -265,17 +271,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
 
             /* Would this overrun our buffer?  If so, we'll die. */
             if (n < bytes_handled + len) {
-                *read = bytes_handled;
-                if (*s) {
-                    /* ensure this string is NUL terminated */
-                    if (bytes_handled > 0) {
-                        (*s)[bytes_handled-1] = '\0';
-                    }
-                    else {
-                        (*s)[0] = '\0';
-                    }
-                }
-                return APR_ENOSPC;
+                rv = APR_ENOSPC;
+                goto cleanup;
             }
 
             /* Do we have to handle the allocation ourselves? */
@@ -283,7 +280,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
                 /* We'll assume the common case where one bucket is enough. */
                 if (!*s) {
                     current_alloc = len;
-                    *s = apr_palloc(r->pool, current_alloc);
+                    *s = apr_palloc(r->pool, current_alloc + 1);
                 }
                 else if (bytes_handled + len > current_alloc) {
                     /* Increase the buffer size */
@@ -294,7 +291,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
                         new_size = (bytes_handled + len) * 2;
                     }
 
-                    new_buffer = apr_palloc(r->pool, new_size);
+                    new_buffer = apr_palloc(r->pool, new_size + 1);
 
                     /* Copy what we already had. */
                     memcpy(new_buffer, *s, bytes_handled);
@@ -343,7 +340,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
             rv = ap_get_brigade(r->input_filters, bb, AP_MODE_SPECULATIVE,
                                 APR_BLOCK_READ, 1);
             if (rv != APR_SUCCESS) {
-                return rv;
+                goto cleanup;
             }
 
             if (APR_BRIGADE_EMPTY(bb)) {
@@ -360,7 +357,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
             rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
             if (rv != APR_SUCCESS) {
                 apr_brigade_cleanup(bb);
-                return rv;
+                goto cleanup;
             }
 
             /* Found one, so call ourselves again to get the next line.
@@ -377,10 +374,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
             if (c == APR_ASCII_BLANK || c == APR_ASCII_TAB) {
                 /* Do we have enough space? We may be full now. */
                 if (bytes_handled >= n) {
-                    *read = n;
-                    /* ensure this string is terminated */
-                    (*s)[n-1] = '\0';
-                    return APR_ENOSPC;
+                    rv = APR_ENOSPC;
+                    goto cleanup;
                 }
                 else {
                     apr_size_t next_size, next_len;
@@ -392,7 +387,6 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
                     if (do_alloc) {
                         tmp = NULL;
                     } else {
-                        /* We're null terminated. */
                         tmp = last_char;
                     }
 
@@ -401,7 +395,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
                     rv = ap_rgetline_core(&tmp, next_size,
                                           &next_len, r, 0, bb);
                     if (rv != APR_SUCCESS) {
-                        return rv;
+                        goto cleanup;
                     }
 
                     if (do_alloc && next_len > 0) {
@@ -415,7 +409,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
                         memcpy(new_buffer, *s, bytes_handled);
 
                         /* copy the new line, including the trailing null */
-                        memcpy(new_buffer + bytes_handled, tmp, next_len + 1);
+                        memcpy(new_buffer + bytes_handled, tmp, next_len);
                         *s = new_buffer;
                     }
 
@@ -428,8 +422,21 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
             }
         }
     }
+
+cleanup:
+    if (bytes_handled >= n) {
+        bytes_handled = n - 1;
+    }
+    if (*s) {
+        /* ensure the string is NUL terminated */
+        (*s)[bytes_handled] = '\0';
+    }
     *read = bytes_handled;
 
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
     /* PR#43039: We shouldn't accept NULL bytes within the line */
     if (strlen(*s) < bytes_handled) {
         return APR_EINVAL;
@@ -468,6 +475,11 @@ AP_DECLARE(int) ap_getline(char *s, int
     apr_size_t len;
     apr_bucket_brigade *tmp_bb;
 
+    if (n < 1) {
+        /* Can't work since we always NUL terminate */
+        return -1;
+    }
+
     tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
     rv = ap_rgetline(&tmp_s, n, &len, r, fold, tmp_bb);
     apr_brigade_destroy(tmp_bb);
