forgot to attach the diff
diff -Nru libapreq2-2.13/debian/changelog libapreq2-2.13/debian/changelog --- libapreq2-2.13/debian/changelog 2019-09-18 09:12:54.000000000 +0200 +++ libapreq2-2.13/debian/changelog 2023-01-19 20:25:21.000000000 +0100 @@ -1,3 +1,10 @@ +libapreq2 (2.13-7~deb11u1) UNRELEASED; urgency=high + + * Non-maintainer upload by the Security Team. + * Backport fix for CVE-2022-22728. (Closes: #1018191) + + -- Tobias Frost <t...@debian.org> Thu, 19 Jan 2023 20:25:21 +0100 + libapreq2 (2.13-7) unstable; urgency=high * Source-only upload. diff -Nru libapreq2-2.13/debian/patches/10-CVE-2022-22728_1of4.patch libapreq2-2.13/debian/patches/10-CVE-2022-22728_1of4.patch --- libapreq2-2.13/debian/patches/10-CVE-2022-22728_1of4.patch 1970-01-01 01:00:00.000000000 +0100 +++ libapreq2-2.13/debian/patches/10-CVE-2022-22728_1of4.patch 2023-01-19 20:24:24.000000000 +0100 @@ -0,0 +1,385 @@ +Description: CVE-2022-22728 -- multipart form parse memory corruption + A flaw in Apache libapreq2 versions 2.16 and earlier could cause a + buffer overflow while processing multipart form uploads. A remote + attacker could send a request causing a process crash which could lead + to a denial of service attack. + This is #1 of 4 patches, see also https://www.openwall.com/lists/oss-security/2023/01/02/2 +Origin: https://svn.apache.org/viewvc?view=revision&revision=1894937 +Bug-Debian: https://bugs.debian.org/1018191 +Reviewed-by: Tobias Frost <t...@debian.org> +Last-Update: 2023-01-13 <YYYY-MM-DD, last update of the meta-information, optional> +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/library/parser_header.c ++++ b/library/parser_header.c +@@ -39,7 +39,10 @@ + HDR_GAP, + HDR_VALUE, + HDR_NEWLINE, +- HDR_CONTINUE, ++ HDR_CONTLINE, ++ HDR_WANTLINE, ++ HDR_NEXTLINE, ++ HDR_LASTLINE, + HDR_COMPLETE, + HDR_ERROR + } status; +@@ -59,16 +62,17 @@ + apreq_value_t *v; + apr_bucket *e, *f; + apr_status_t s; +- struct iovec vec[APREQ_DEFAULT_NELTS], *iov, *end; +- apr_array_header_t arr; ++ struct iovec vec[APREQ_DEFAULT_NELTS], *iov; ++ apr_array_header_t arr, *a = &arr; + char *dest; + const char *data; + apr_size_t dlen; ++ int i; + + if (nlen == 0) + return APR_EBADARG; + +- param = apreq_param_make(pool, NULL, nlen, NULL, vlen - 1); /*drop (CR)LF */ ++ param = apreq_param_make(pool, NULL, nlen, NULL, vlen); + *(const apreq_value_t **)&v = ¶m->v; + + arr.pool = pool; +@@ -80,67 +84,78 @@ + e = APR_BRIGADE_FIRST(bb); + + /* store name in a temporary iovec array */ +- + while (nlen > 0) { + apr_size_t len; +- end = apr_array_push(&arr); +- s = apr_bucket_read(e, (const char **)&end->iov_base, ++ ++ if (a->nelts == a->nalloc) { ++ a = apr_array_make(pool, arr.nalloc * 2, sizeof(struct iovec)); ++ memcpy(a->elts, arr.elts, arr.nelts * sizeof(struct iovec)); ++ a->nelts = arr.nelts; ++ } ++ iov = (struct iovec *)apr_array_push(a); ++ ++ assert(e != APR_BRIGADE_SENTINEL(bb)); ++ s = apr_bucket_read(e, (const char **)&iov->iov_base, + &len, APR_BLOCK_READ); + if (s != APR_SUCCESS) + return s; ++ iov->iov_len = len; + + assert(nlen >= len); +- end->iov_len = len; + nlen -= len; + + e = APR_BUCKET_NEXT(e); + } + + /* skip gap */ +- + while (glen > 0) { ++ assert(e != APR_BRIGADE_SENTINEL(bb)); + s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); + if (s != APR_SUCCESS) + return s; + + assert(glen >= dlen); + glen -= dlen; ++ + e = APR_BUCKET_NEXT(e); + } + + /* copy value */ +- assert(vlen > 0); + dest = v->data; + while (vlen > 0) { ++ apr_size_t off; + ++ assert(e != APR_BRIGADE_SENTINEL(bb)); + s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); + if (s != APR_SUCCESS) + return s; + +- memcpy(dest, data, dlen); +- dest += dlen; +- assert(vlen >= dlen); +- vlen -= dlen; ++ for (off = 0; off < dlen; ++off) { ++ const char ch = data[off]; ++ if (ch == '\r' || ch == '\n') { ++ /* skip continuation CRLF(s) */ ++ continue; ++ } ++ assert(vlen > 0); ++ *dest = ch; ++ ++dest; ++ --vlen; ++ } ++ + e = APR_BUCKET_NEXT(e); + } +- +- assert(dest[-1] == '\n'); +- +- if (dest[-2] == '\r') +- --dest; +- +- dest[-1] = 0; +- v->dlen = (dest - v->data) - 1; ++ v->dlen = dest - v->data; ++ *dest++ = 0; + + /* write name */ + v->name = dest; +- iov = (struct iovec *)arr.elts; +- +- while (iov <= end) { ++ for (i = 0; i < a->nelts; ++i) { ++ iov = (struct iovec *)a->elts + i; + memcpy(dest, iov->iov_base, iov->iov_len); + dest += iov->iov_len; + ++iov; + } ++ v->nlen = dest - v->name; + *dest = 0; + nlen = dest - v->name; + +@@ -159,6 +174,7 @@ + apr_pool_t *pool = parser->pool; + apr_bucket *e; + struct hdr_ctx *ctx; ++ char ch; + + if (parser->ctx == NULL) { + ctx = apr_pcalloc(pool, sizeof *ctx); +@@ -173,9 +189,6 @@ + e = APR_BRIGADE_LAST(ctx->bb); + APR_BRIGADE_CONCAT(ctx->bb, bb); + +- parse_hdr_brigade: +- +- + /* parse the brigade for CRLF_CRLF-terminated header block, + * each time starting from the front of the brigade. + */ +@@ -194,8 +207,8 @@ + APR_BRIGADE_CONCAT(bb, ctx->bb); + return APR_SUCCESS; + } +- s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); + ++ s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); + if ( s != APR_SUCCESS ) { + ctx->status = HDR_ERROR; + return s; +@@ -217,21 +230,8 @@ + case HDR_NAME: + + while (off < dlen) { +- switch (data[off++]) { +- +- case '\n': +- if (off < dlen) +- apr_bucket_split(e, off); +- e = APR_BUCKET_NEXT(e); +- +- do { +- apr_bucket *f = APR_BRIGADE_FIRST(ctx->bb); +- apr_bucket_delete(f); +- } while (e != APR_BRIGADE_FIRST(ctx->bb)); +- APR_BRIGADE_CONCAT(bb, ctx->bb); +- ctx->status = HDR_COMPLETE; +- return APR_SUCCESS; +- ++ ch = data[off++]; ++ switch (ch) { + case ':': + if (off > 1) { + apr_bucket_split(e, off - 1); +@@ -247,16 +247,15 @@ + default: + ++ctx->nlen; + } +- + } +- + break; + + + case HDR_GAP: + + while (off < dlen) { +- switch (data[off++]) { ++ ch = data[off++]; ++ switch (ch) { + case ' ': + case '\t': + ++ctx->glen; +@@ -266,6 +265,10 @@ + ctx->status = HDR_NEWLINE; + goto parse_hdr_bucket; + ++ case '\r': ++ ctx->status = HDR_WANTLINE; ++ goto parse_hdr_bucket; ++ + default: + ctx->status = HDR_VALUE; + if (off > 1) { +@@ -285,25 +288,52 @@ + case HDR_VALUE: + + while (off < dlen) { +- ++ctx->vlen; +- if (data[off++] == '\n') { ++ ch = data[off++]; ++ switch (ch) { ++ case '\n': + ctx->status = HDR_NEWLINE; + goto parse_hdr_bucket; ++ ++ case '\r': ++ ctx->status = HDR_WANTLINE; ++ goto parse_hdr_bucket; ++ ++ default: ++ ++ctx->vlen; + } + } + break; + + ++ case HDR_WANTLINE: ++ case HDR_LASTLINE: ++ ++ if (off == dlen) ++ break; ++ ++ if (data[off++] != '\n') { ++ ctx->status = HDR_ERROR; ++ return APR_EINVAL; ++ } ++ ++ if (ctx->status == HDR_LASTLINE) { ++ ctx->status = HDR_COMPLETE; ++ goto parse_hdr_bucket; ++ } ++ ++ /* fall thru */ ++ ctx->status = HDR_NEWLINE; ++ + case HDR_NEWLINE: + + if (off == dlen) + break; +- else { +- switch (data[off]) { + ++ { ++ ch = data[off]; ++ switch (ch) { + case ' ': + case '\t': +- ctx->status = HDR_CONTINUE; + ++off; + ++ctx->vlen; + break; +@@ -315,30 +345,29 @@ + s = split_header_line(¶m, pool, ctx->bb, ctx->nlen, ctx->glen, ctx->vlen); + if (parser->hook != NULL && s == APR_SUCCESS) + s = apreq_hook_run(parser->hook, param, NULL); +- + if (s != APR_SUCCESS) { + ctx->status = HDR_ERROR; + return s; + } + + apreq_value_table_add(¶m->v, t); +- e = APR_BRIGADE_SENTINEL(ctx->bb); +- ctx->status = HDR_NAME; + ctx->nlen = 0; + ctx->vlen = 0; + ctx->glen = 0; + +- goto parse_hdr_brigade; ++ ctx->status = HDR_NEXTLINE; ++ goto parse_hdr_bucket; + } +- +- /* cases ' ', '\t' fall through to HDR_CONTINUE */ + } + ++ /* fall thru */ ++ ctx->status = HDR_CONTLINE; + +- case HDR_CONTINUE: ++ case HDR_CONTLINE: + + while (off < dlen) { +- switch (data[off++]) { ++ ch = data[off++]; ++ switch (ch) { + case ' ': + case '\t': + ++ctx->vlen; +@@ -348,6 +377,10 @@ + ctx->status = HDR_NEWLINE; + goto parse_hdr_bucket; + ++ case '\r': ++ ctx->status = HDR_WANTLINE; ++ goto parse_hdr_bucket; ++ + default: + ctx->status = HDR_VALUE; + ++ctx->vlen; +@@ -356,8 +389,47 @@ + } + break; + ++ ++ case HDR_NEXTLINE: ++ ++ if (off == dlen) ++ break; ++ ++ ch = data[off++]; ++ switch (ch) { ++ case '\n': ++ /* We are done */ ++ break; ++ ++ case '\r': ++ ctx->status = HDR_LASTLINE; ++ goto parse_hdr_bucket; ++ ++ default: ++ ctx->status = HDR_NAME; ++ goto parse_hdr_bucket; ++ } ++ ++ /* fall thru */ ++ ctx->status = HDR_COMPLETE; ++ ++ case HDR_COMPLETE: ++ ++ if (off < dlen) ++ apr_bucket_split(e, off); ++ ++ e = APR_BUCKET_NEXT(e); ++ do { ++ apr_bucket *f = APR_BRIGADE_FIRST(ctx->bb); ++ apr_bucket_delete(f); ++ } while (e != APR_BRIGADE_FIRST(ctx->bb)); ++ ++ APR_BRIGADE_CONCAT(bb, ctx->bb); ++ return APR_SUCCESS; ++ ++ + default: +- ; /* not reached */ ++ assert(0); /* not reached */ + } + } + apreq_brigade_setaside(ctx->bb,pool); diff -Nru libapreq2-2.13/debian/patches/11-CVE-2022-22728_2of4.patch libapreq2-2.13/debian/patches/11-CVE-2022-22728_2of4.patch --- libapreq2-2.13/debian/patches/11-CVE-2022-22728_2of4.patch 1970-01-01 01:00:00.000000000 +0100 +++ libapreq2-2.13/debian/patches/11-CVE-2022-22728_2of4.patch 2023-01-19 20:24:31.000000000 +0100 @@ -0,0 +1,89 @@ +Description: CVE-2022-22728 -- multipart form parse memory corruption + A flaw in Apache libapreq2 versions 2.16 and earlier could cause a + buffer overflow while processing multipart form uploads. A remote + attacker could send a request causing a process crash which could lead + to a denial of service attack. + This is #2 of 4 patches, see alos https://www.openwall.com/lists/oss-security/2023/01/02/2 +Origin: https://svn.apache.org/viewvc?view=revision&revision=1894940 +Bug-Debian: https://bugs.debian.org/1018191 +Reviewed-by: Tobias Frost <t...@debian.org> +Last-Update: 2023-01-13 <YYYY-MM-DD, last update of the meta-information, optional> +--- a/library/parser_header.c ++++ b/library/parser_header.c +@@ -39,7 +39,7 @@ + HDR_GAP, + HDR_VALUE, + HDR_NEWLINE, +- HDR_CONTLINE, ++ HDR_FOLDLINE, + HDR_WANTLINE, + HDR_NEXTLINE, + HDR_LASTLINE, +@@ -329,41 +329,39 @@ + if (off == dlen) + break; + +- { +- ch = data[off]; +- switch (ch) { +- case ' ': +- case '\t': +- ++off; +- ++ctx->vlen; +- break; ++ ch = data[off]; ++ switch (ch) { ++ case ' ': ++ case '\t': ++ ++off; ++ ++ctx->vlen; ++ break; + +- default: +- /* can parse brigade now */ +- if (off > 0) +- apr_bucket_split(e, off); +- s = split_header_line(¶m, pool, ctx->bb, ctx->nlen, ctx->glen, ctx->vlen); +- if (parser->hook != NULL && s == APR_SUCCESS) +- s = apreq_hook_run(parser->hook, param, NULL); +- if (s != APR_SUCCESS) { +- ctx->status = HDR_ERROR; +- return s; +- } ++ default: ++ /* can parse brigade now */ ++ if (off > 0) ++ apr_bucket_split(e, off); ++ s = split_header_line(¶m, pool, ctx->bb, ctx->nlen, ctx->glen, ctx->vlen); ++ if (parser->hook != NULL && s == APR_SUCCESS) ++ s = apreq_hook_run(parser->hook, param, NULL); ++ if (s != APR_SUCCESS) { ++ ctx->status = HDR_ERROR; ++ return s; ++ } + +- apreq_value_table_add(¶m->v, t); +- ctx->nlen = 0; +- ctx->vlen = 0; +- ctx->glen = 0; ++ apreq_value_table_add(¶m->v, t); ++ ctx->nlen = 0; ++ ctx->vlen = 0; ++ ctx->glen = 0; + +- ctx->status = HDR_NEXTLINE; +- goto parse_hdr_bucket; +- } ++ ctx->status = HDR_NEXTLINE; ++ goto parse_hdr_bucket; + } + + /* fall thru */ +- ctx->status = HDR_CONTLINE; ++ ctx->status = HDR_FOLDLINE; + +- case HDR_CONTLINE: ++ case HDR_FOLDLINE: + + while (off < dlen) { + ch = data[off++]; diff -Nru libapreq2-2.13/debian/patches/12-CVE-2022-22728_3of4.patch libapreq2-2.13/debian/patches/12-CVE-2022-22728_3of4.patch --- libapreq2-2.13/debian/patches/12-CVE-2022-22728_3of4.patch 1970-01-01 01:00:00.000000000 +0100 +++ libapreq2-2.13/debian/patches/12-CVE-2022-22728_3of4.patch 2023-01-19 20:24:40.000000000 +0100 @@ -0,0 +1,351 @@ +Description: CVE-2022-22728 -- multipart form parse memory corruption + A flaw in Apache libapreq2 versions 2.16 and earlier could cause a + buffer overflow while processing multipart form uploads. A remote + attacker could send a request causing a process crash which could lead + to a denial of service attack. + This is #3 of 4 patches, see alos https://www.openwall.com/lists/oss-security/2023/01/02/2 +Origin: https://svn.apache.org/viewvc?view=revision&revision=1894977 +Bug-Debian: https://bugs.debian.org/1018191 +Reviewed-by: Tobias Frost <t...@debian.org> +Last-Update: 2023-01-13 <YYYY-MM-DD, last update of the meta-information, optional> +--- a/library/parser_header.c ++++ b/library/parser_header.c +@@ -19,6 +19,8 @@ + #include "apreq_error.h" + #include "apreq_util.h" + ++#include "apr_lib.h" /* for apr_iscntrl() & co */ ++ + #define PARSER_STATUS_CHECK(PREFIX) do { \ + if (ctx->status == PREFIX##_ERROR) \ + return APREQ_ERROR_GENERAL; \ +@@ -39,9 +41,8 @@ + HDR_GAP, + HDR_VALUE, + HDR_NEWLINE, ++ HDR_ENDLINE, + HDR_FOLDLINE, +- HDR_WANTLINE, +- HDR_NEXTLINE, + HDR_LASTLINE, + HDR_COMPLETE, + HDR_ERROR +@@ -51,27 +52,37 @@ + /********************* header parsing utils ********************/ + + +-static apr_status_t split_header_line(apreq_param_t **p, +- apr_pool_t *pool, +- apr_bucket_brigade *bb, +- apr_size_t nlen, +- apr_size_t glen, +- apr_size_t vlen) ++static apr_bucket *split_header_line(apr_bucket *e, apr_size_t *off, ++ const char **data, apr_size_t *dlen) ++{ ++ if (*off > 1) { ++ apr_bucket_split(e, *off - 1); ++ e = APR_BUCKET_NEXT(e); ++ *dlen -= *off - 1; ++ *data += *off - 1; ++ *off = 1; ++ } ++ return e; ++} ++ ++static apr_status_t consume_header_line(apreq_param_t **p, ++ apr_pool_t *pool, ++ apr_bucket_brigade *bb, ++ apr_size_t nlen, ++ apr_size_t glen, ++ apr_size_t vlen) + { + apreq_param_t *param; + apreq_value_t *v; + apr_bucket *e, *f; + apr_status_t s; + struct iovec vec[APREQ_DEFAULT_NELTS], *iov; +- apr_array_header_t arr, *a = &arr; ++ apr_array_header_t arr; + char *dest; + const char *data; + apr_size_t dlen; + int i; + +- if (nlen == 0) +- return APR_EBADARG; +- + param = apreq_param_make(pool, NULL, nlen, NULL, vlen); + *(const apreq_value_t **)&v = ¶m->v; + +@@ -84,17 +95,11 @@ + e = APR_BRIGADE_FIRST(bb); + + /* store name in a temporary iovec array */ +- while (nlen > 0) { ++ do { + apr_size_t len; + +- if (a->nelts == a->nalloc) { +- a = apr_array_make(pool, arr.nalloc * 2, sizeof(struct iovec)); +- memcpy(a->elts, arr.elts, arr.nelts * sizeof(struct iovec)); +- a->nelts = arr.nelts; +- } +- iov = (struct iovec *)apr_array_push(a); +- + assert(e != APR_BRIGADE_SENTINEL(bb)); ++ iov = (struct iovec *)apr_array_push(&arr); + s = apr_bucket_read(e, (const char **)&iov->iov_base, + &len, APR_BLOCK_READ); + if (s != APR_SUCCESS) +@@ -105,10 +110,10 @@ + nlen -= len; + + e = APR_BUCKET_NEXT(e); +- } ++ } while (nlen > 0); + + /* skip gap */ +- while (glen > 0) { ++ do { + assert(e != APR_BRIGADE_SENTINEL(bb)); + s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); + if (s != APR_SUCCESS) +@@ -118,11 +123,11 @@ + glen -= dlen; + + e = APR_BUCKET_NEXT(e); +- } ++ } while (glen > 0); + + /* copy value */ + dest = v->data; +- while (vlen > 0) { ++ do { + apr_size_t off; + + assert(e != APR_BRIGADE_SENTINEL(bb)); +@@ -143,14 +148,14 @@ + } + + e = APR_BUCKET_NEXT(e); +- } ++ } while (vlen > 0); + v->dlen = dest - v->data; + *dest++ = 0; + + /* write name */ + v->name = dest; +- for (i = 0; i < a->nelts; ++i) { +- iov = (struct iovec *)a->elts + i; ++ for (i = 0; i < arr.nelts; ++i) { ++ iov = &((struct iovec *)arr.elts)[i]; + memcpy(dest, iov->iov_base, iov->iov_len); + dest += iov->iov_len; + ++iov; +@@ -168,6 +173,8 @@ + + } + ++#define IS_TOKEN_CHAR(c) (apr_isalnum(c) \ ++ || ((c) && strchr("!#$%&'*+-.^_`|~", (c)))) + + APREQ_DECLARE_PARSER(apreq_parse_headers) + { +@@ -233,18 +240,20 @@ + ch = data[off++]; + switch (ch) { + case ':': +- if (off > 1) { +- apr_bucket_split(e, off - 1); +- dlen -= off - 1; +- data += off - 1; +- off = 1; +- e = APR_BUCKET_NEXT(e); ++ if (!ctx->nlen) { ++ ctx->status = HDR_ERROR; ++ return APREQ_ERROR_BADHEADER; + } ++ e = split_header_line(e, &off, &data, &dlen); + ++ctx->glen; + ctx->status = HDR_GAP; + goto parse_hdr_bucket; + + default: ++ if (!IS_TOKEN_CHAR(ch)) { ++ ctx->status = HDR_ERROR; ++ return APREQ_ERROR_BADCHAR; ++ } + ++ctx->nlen; + } + } +@@ -262,23 +271,23 @@ + break; + + case '\n': ++ e = split_header_line(e, &off, &data, &dlen); + ctx->status = HDR_NEWLINE; + goto parse_hdr_bucket; + + case '\r': +- ctx->status = HDR_WANTLINE; ++ e = split_header_line(e, &off, &data, &dlen); ++ ctx->status = HDR_ENDLINE; + goto parse_hdr_bucket; + + default: +- ctx->status = HDR_VALUE; +- if (off > 1) { +- apr_bucket_split(e, off - 1); +- dlen -= off - 1; +- data += off - 1; +- off = 1; +- e = APR_BUCKET_NEXT(e); ++ if (apr_iscntrl(ch)) { ++ ctx->status = HDR_ERROR; ++ return APREQ_ERROR_BADCHAR; + } ++ e = split_header_line(e, &off, &data, &dlen); + ++ctx->vlen; ++ ctx->status = HDR_VALUE; + goto parse_hdr_bucket; + } + } +@@ -295,17 +304,21 @@ + goto parse_hdr_bucket; + + case '\r': +- ctx->status = HDR_WANTLINE; ++ ctx->status = HDR_ENDLINE; + goto parse_hdr_bucket; + + default: ++ if (apr_iscntrl(ch)) { ++ ctx->status = HDR_ERROR; ++ return APREQ_ERROR_BADCHAR; ++ } + ++ctx->vlen; + } + } + break; + + +- case HDR_WANTLINE: ++ case HDR_ENDLINE: + case HDR_LASTLINE: + + if (off == dlen) +@@ -313,7 +326,7 @@ + + if (data[off++] != '\n') { + ctx->status = HDR_ERROR; +- return APR_EINVAL; ++ return APREQ_ERROR_BADHEADER; + } + + if (ctx->status == HDR_LASTLINE) { +@@ -329,32 +342,48 @@ + if (off == dlen) + break; + +- ch = data[off]; ++ ch = data[off++]; + switch (ch) { + case ' ': + case '\t': +- ++off; + ++ctx->vlen; + break; + + default: +- /* can parse brigade now */ +- if (off > 0) +- apr_bucket_split(e, off); +- s = split_header_line(¶m, pool, ctx->bb, ctx->nlen, ctx->glen, ctx->vlen); ++ e = split_header_line(e, &off, &data, &dlen); ++ ++ /* consume from splitted brigade now */ ++ s = consume_header_line(¶m, pool, ctx->bb, ++ ctx->nlen, ctx->glen, ctx->vlen); + if (parser->hook != NULL && s == APR_SUCCESS) + s = apreq_hook_run(parser->hook, param, NULL); + if (s != APR_SUCCESS) { + ctx->status = HDR_ERROR; + return s; + } +- + apreq_value_table_add(¶m->v, t); + ctx->nlen = 0; + ctx->vlen = 0; + ctx->glen = 0; + +- ctx->status = HDR_NEXTLINE; ++ switch (ch) { ++ case '\n': ++ ctx->status = HDR_COMPLETE; ++ break; ++ ++ case '\r': ++ ctx->status = HDR_LASTLINE; ++ break; ++ ++ default: ++ if (!IS_TOKEN_CHAR(ch)) { ++ ctx->status = HDR_ERROR; ++ return APREQ_ERROR_BADCHAR; ++ } ++ ++ctx->nlen; ++ ctx->status = HDR_NAME; ++ break; ++ } + goto parse_hdr_bucket; + } + +@@ -376,10 +405,14 @@ + goto parse_hdr_bucket; + + case '\r': +- ctx->status = HDR_WANTLINE; ++ ctx->status = HDR_ENDLINE; + goto parse_hdr_bucket; + + default: ++ if (apr_iscntrl(ch)) { ++ ctx->status = HDR_ERROR; ++ return APREQ_ERROR_BADCHAR; ++ } + ctx->status = HDR_VALUE; + ++ctx->vlen; + goto parse_hdr_bucket; +@@ -388,30 +421,7 @@ + break; + + +- case HDR_NEXTLINE: +- +- if (off == dlen) +- break; +- +- ch = data[off++]; +- switch (ch) { +- case '\n': +- /* We are done */ +- break; +- +- case '\r': +- ctx->status = HDR_LASTLINE; +- goto parse_hdr_bucket; +- +- default: +- ctx->status = HDR_NAME; +- goto parse_hdr_bucket; +- } +- +- /* fall thru */ +- ctx->status = HDR_COMPLETE; +- +- case HDR_COMPLETE: ++ case HDR_COMPLETE: + + if (off < dlen) + apr_bucket_split(e, off); diff -Nru libapreq2-2.13/debian/patches/13-CVE-2022-22728_4of4.patch libapreq2-2.13/debian/patches/13-CVE-2022-22728_4of4.patch --- libapreq2-2.13/debian/patches/13-CVE-2022-22728_4of4.patch 1970-01-01 01:00:00.000000000 +0100 +++ libapreq2-2.13/debian/patches/13-CVE-2022-22728_4of4.patch 2023-01-19 20:25:00.000000000 +0100 @@ -0,0 +1,50 @@ +Description: CVE-2022-22728 -- multipart form parse memory corruption + A flaw in Apache libapreq2 versions 2.16 and earlier could cause a + buffer overflow while processing multipart form uploads. A remote + attacker could send a request causing a process crash which could lead + to a denial of service attack. + This is #4 of 4 patches, see alos https://www.openwall.com/lists/oss-security/2023/01/02/2 +Origin: https://svn.apache.org/viewvc?view=revision&revision=1895054 +Bug-Debian: https://bugs.debian.org/1018191 +Reviewed-by: Tobias Frost <t...@debian.org> +Last-Update: 2023-01-13 <YYYY-MM-DD, last update of the meta-information, optional> +--- a/library/parser_header.c ++++ b/library/parser_header.c +@@ -81,7 +81,7 @@ + char *dest; + const char *data; + apr_size_t dlen; +- int i; ++ int i, eol = 0; + + param = apreq_param_make(pool, NULL, nlen, NULL, vlen); + *(const apreq_value_t **)&v = ¶m->v; +@@ -138,7 +138,9 @@ + for (off = 0; off < dlen; ++off) { + const char ch = data[off]; + if (ch == '\r' || ch == '\n') { +- /* skip continuation CRLF(s) */ ++ /* Eat [CR]LF of continuation or end of line */ ++ if (!vlen && ch == '\n') ++ eol = 1; /* done */ + continue; + } + assert(vlen > 0); +@@ -148,7 +150,7 @@ + } + + e = APR_BUCKET_NEXT(e); +- } while (vlen > 0); ++ } while (!eol); + v->dlen = dest - v->data; + *dest++ = 0; + +@@ -421,7 +423,7 @@ + break; + + +- case HDR_COMPLETE: ++ case HDR_COMPLETE: + + if (off < dlen) + apr_bucket_split(e, off); diff -Nru libapreq2-2.13/debian/patches/series libapreq2-2.13/debian/patches/series --- libapreq2-2.13/debian/patches/series 2019-09-15 18:26:35.000000000 +0200 +++ libapreq2-2.13/debian/patches/series 2023-01-19 20:24:47.000000000 +0100 @@ -3,3 +3,7 @@ 03-link-in-apr-shared-objects.patch 04-pass-libdir-to-configure.patch 05-nested-multipart-null-dereference.patch +10-CVE-2022-22728_1of4.patch +11-CVE-2022-22728_2of4.patch +12-CVE-2022-22728_3of4.patch +13-CVE-2022-22728_4of4.patch