Index: httpd-2.2.34/modules/proxy/mod_proxy_ftp.c
===================================================================
--- httpd-2.2.34.orig/modules/proxy/mod_proxy_ftp.c	2020-04-06 12:24:31.062311278 +0200
+++ httpd-2.2.34/modules/proxy/mod_proxy_ftp.c	2020-04-06 12:27:57.783315522 +0200
@@ -216,6 +216,75 @@ static int proxy_ftp_canon(request_rec *
     return OK;
 }
 
+static apr_status_t ftp_string_read(conn_rec *c, apr_bucket_brigade *bb,
+        char *buff, apr_size_t bufflen, int *eos, apr_size_t *outlen)
+{
+    apr_bucket *e;
+    apr_status_t rv;
+    char *pos = buff;
+    char *response;
+    int found = 0;
+    apr_size_t len;
+
+    /* start with an empty string */
+    buff[0] = 0;
+    *eos = 0;
+    *outlen = 0;
+
+    /* loop through each brigade */
+    while (!found) {
+        /* get brigade from network one line at a time */
+        if (APR_SUCCESS != (rv = ap_get_brigade(c->input_filters, bb,
+                                                AP_MODE_GETLINE,
+                                                APR_BLOCK_READ,
+                                                0))) {
+            return rv;
+        }
+        /* loop through each bucket */
+        while (!found) {
+            if (*eos || APR_BRIGADE_EMPTY(bb)) {
+                /* The connection aborted or timed out */
+                return APR_ECONNABORTED;
+            }
+            e = APR_BRIGADE_FIRST(bb);
+            if (APR_BUCKET_IS_EOS(e)) {
+                *eos = 1;
+            }
+            else {
+                if (APR_SUCCESS != (rv = apr_bucket_read(e,
+                                                         (const char **)&response,
+                                                         &len,
+                                                         APR_BLOCK_READ))) {
+                    return rv;
+                }
+                /*
+                 * is string LF terminated?
+                 * XXX: This check can be made more efficient by simply checking
+                 * if the last character in the 'response' buffer is an ASCII_LF.
+                 * See ap_rgetline() for an example.
+                 */
+                if (memchr(response, APR_ASCII_LF, len)) {
+                    found = 1;
+                }   
+                /* concat strings until buff is full - then throw the data away */
+                if (len > ((bufflen-1)-(pos-buff))) {
+                    len = (bufflen-1)-(pos-buff);
+                }   
+                if (len > 0) {
+                    memcpy(pos, response, len);
+                    pos += len; 
+                    *outlen += len;
+                }   
+            }   
+            apr_bucket_delete(e);
+        }   
+        *pos = '\0';
+    }   
+    
+    return APR_SUCCESS;
+}
+
+
 /* we chop lines longer than 80 characters */
 #define MAX_LINE_LEN 80
 
@@ -231,27 +300,34 @@ static int ftp_getrc_msg(conn_rec *ftp_c
     char *mb = msgbuf, *me = &msgbuf[msglen];
     apr_status_t rv;
     int eos;
+    apr_size_t nread;
 
-    if (APR_SUCCESS != (rv = ap_proxy_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) {
+    if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos, &nread))) {
         return -1;
     }
 /*
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
                  "proxy: <FTP: %s", response);
 */
+    if (nread < 4) { 
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, "Malformed FTP response '%s'", response);
+        *mb = '\0';
+        return -1;
+    }
+
     if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) ||
-    !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-'))
+        !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-'))
         status = 0;
     else
         status = 100 * response[0] + 10 * response[1] + response[2] - 111 * '0';
 
     mb = apr_cpystrn(mb, response + 4, me - mb);
 
-    if (response[3] == '-') {
+    if (response[3] == '-') { /* multi-line reply "123-foo\nbar\n123 baz" */
         memcpy(buff, response, 3);
         buff[3] = ' ';
         do {
-            if (APR_SUCCESS != (rv = ap_proxy_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) {
+            if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos, &nread))) {
                 return -1;
             }
             mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb);
