Bug#1029217: bullseye-pu: package libapreq2/2.13-7~deb11u1
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 <tobi@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 <tobi@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 <tobi@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 <tobi@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 <tobi@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
Reply to: