Version in base suite: 0.11-1 Base version: xfpt_0.11-1 Target version: xfpt_0.11-1+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/x/xfpt/xfpt_0.11-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/x/xfpt/xfpt_0.11-1+deb12u1.dsc changelog | 8 patches/30-Diagnose-error-if-macro-expansion-makes-a-line-too-l.patch | 280 ++++++++++ patches/series | 1 3 files changed, 289 insertions(+) diff -Nru xfpt-0.11/debian/changelog xfpt-0.11/debian/changelog --- xfpt-0.11/debian/changelog 2020-09-18 09:13:36.000000000 +0000 +++ xfpt-0.11/debian/changelog 2024-10-19 11:32:57.000000000 +0000 @@ -1,3 +1,11 @@ +xfpt (0.11-1+deb12u1) bookworm; urgency=medium + + * Cherry-pick 30-Diagnose-error-if-macro-expansion-makes-a-line-too-l.patch + from upstream GIT master to fix buffer overflow CVE-2024-43700. + Closes: #1080219 + + -- Andreas Metzler Sat, 19 Oct 2024 13:32:57 +0200 + xfpt (0.11-1) unstable; urgency=low * Fix watchfile (report functionality). diff -Nru xfpt-0.11/debian/patches/30-Diagnose-error-if-macro-expansion-makes-a-line-too-l.patch xfpt-0.11/debian/patches/30-Diagnose-error-if-macro-expansion-makes-a-line-too-l.patch --- xfpt-0.11/debian/patches/30-Diagnose-error-if-macro-expansion-makes-a-line-too-l.patch 1970-01-01 00:00:00.000000000 +0000 +++ xfpt-0.11/debian/patches/30-Diagnose-error-if-macro-expansion-makes-a-line-too-l.patch 2024-10-19 11:32:57.000000000 +0000 @@ -0,0 +1,280 @@ +From a690304bbd3fd19e9dfdad50dcc87ad829f744e4 Mon Sep 17 00:00:00 2001 +From: Philip Hazel +Date: Sun, 11 Aug 2024 17:43:41 +0100 +Subject: [PATCH] Diagnose error if macro expansion makes a line too long for + its buffer + +--- + ChangeLog | 7 +++++++ + src/dot.c | 9 +++++++-- + src/error.c | 7 ++++--- + src/functions.h | 4 ++-- + src/globals.c | 4 ++-- + src/para.c | 5 +++-- + src/read.c | 27 +++++++++++++++++++++------ + src/structs.h | 3 ++- + testing/infiles/07 | 5 +++++ + testing/outfiles/07 | 1 + + testing/outfiles/07.err | 4 ++++ + testing/outfiles/cmd.err | 2 +- + 12 files changed, 59 insertions(+), 19 deletions(-) + create mode 100644 testing/infiles/07 + create mode 100644 testing/outfiles/07 + create mode 100644 testing/outfiles/07.err + +--- a/src/dot.c ++++ b/src/dot.c +@@ -467,10 +467,11 @@ while (*p != 0) + argstr *as = misc_malloc(sizeof(argstr)); + as->next = NULL; + *pp = as; + pp = &(as->next); + as->string = misc_readitem(p, NULL, &length, NULL, 0); ++ as->length = length; + p += length; + } + + pp = &(md->lines); + for (;;) +@@ -488,21 +489,24 @@ for (;;) + + as = misc_malloc(sizeof(argstr)); + as->next = NULL; + *pp = as; + pp = &(as->next); +- as->string = misc_copystring(line, Ustrlen(line)); ++ length = Ustrlen(line); ++ as->string = misc_copystring(line, length); ++ as->length = length; + } + + /* If there aren't any replacement lines, fake up a comment so that there's + always something for a macro to generate. */ + + if (md->lines == NULL) + { + md->lines = misc_malloc(sizeof(argstr)); + md->lines->next = NULL; + md->lines->string = misc_copystring(US". Dummy line\n", 13); ++ md->lines->length = 13; + } + } + + + +@@ -900,10 +904,11 @@ while (*p != 0) + argstr *as = misc_malloc(sizeof(argstr)); + as->next = NULL; + *pp = as; + pp = &(as->next); + as->string = misc_readitem(p, NULL, &length, NULL, 0); ++ as->length = length; + p += length; + } + } + + /* End of dot.c */ +--- a/src/error.c ++++ b/src/error.c +@@ -78,11 +78,12 @@ static error_struct error_data[] = { + { ec_serious, "\".nest end\" incorrectly nested" }, + { ec_serious, "missing delimiter after $=%d at end of line" }, + /* 30-34 */ + { ec_serious, "bad macro argument substitution: %s follows \"%s\"" }, + { ec_serious, "binary zero in input ignored" }, +-{ ec_disaster, "input sources too deeply nested" } ++{ ec_disaster, "input sources too deeply nested" }, ++{ ec_disaster, "maximum line length exceeded during macro substitution" } + }; + + #define error_maxerror (int)(sizeof(error_data)/sizeof(error_struct)) + + +--- a/src/functions.h ++++ b/src/functions.h +@@ -20,11 +20,11 @@ extern uschar *misc_readstring(uscha + + extern void para_process(uschar *); + + extern uschar *read_nextline(void); + extern uschar *read_paragraph(uschar *, int *); +-extern void read_process_macroline(uschar *, uschar *); ++extern void read_process_macroline(uschar *, uschar *, int); + + extern int tree_insertnode(tree_node **, tree_node *); + extern tree_node *tree_search(tree_node *, uschar *); + + /* End of functions.h */ +--- a/src/para.c ++++ b/src/para.c +@@ -66,10 +66,11 @@ while (*q != 0 && *q != ')') + argstr *as = misc_malloc(sizeof(argstr)); + as->next = NULL; + *pp = as; + pp = &(as->next); + as->string = misc_readitem(q, US",)", &length, NULL, 0); ++ as->length = length; + q += length; + if (*q == ',') while (isspace(*(++q))); + } + + if (*q != ')') +@@ -88,11 +89,11 @@ para_inline_macro++; + + for (;;) + { + uschar buffer[INBUFFSIZE]; + +- read_process_macroline(macrocurrent->nextline->string, buffer); ++ read_process_macroline(macrocurrent->nextline->string, buffer, INBUFFSIZE); + + /* A directive such as .eacharg can skip to the end of the macro if there + is no .endeach. Detect this by looking for a change of macrocurrent value, + because there may be an enclosing macro. */ + +--- a/src/read.c ++++ b/src/read.c +@@ -29,11 +29,11 @@ Arguments: + + Returns: nothing + */ + + void +-read_process_macroline(uschar *p, uschar *b) ++read_process_macroline(uschar *p, uschar *b, int blen) + { + int optend = 0; + + while (*p != 0) + { +@@ -49,21 +49,27 @@ while (*p != 0) + optend = 0; + p++; + continue; + } + ++ /* Ensure at least 3 bytes left in the buffer because all cases except an ++ argument substitution (which does its own test) add no more than two bytes, ++ and the third is for the terminating zero. */ ++ ++ if (blen < 3) error(33); /* Hard error; does not return. */ ++ + /* Until we hit a dollar, just copy verbatim */ + +- if (*p != '$') { *b++ = *p++; continue; } ++ if (*p != '$') { *b++ = *p++; blen--; continue; } + + /* If dollar is at the end of the string, treat as literal. */ + + if (p[1] == 0) { *b++ = '$'; break; } + + /* If the character after $ is another $, insert a literal $. */ + +- if (p[1] == '$') { p++; *b++ = *p++; continue; } ++ if (p[1] == '$') { p++; *b++ = *p++; blen--; continue; } + + /* If the character after $ is +, we are dealing with arguments + relative to macro_arg0 in a ".eacharg" section. Otherwise, we are dealing + with an absolute argument number. */ + +@@ -73,10 +79,11 @@ while (*p != 0) + if (macro_argbase == NULL) /* Not in a .eacharg section */ + { + error(18); + *b++ = '$'; + *b++ = *p++; ++ blen -= 2; + continue; + } + argbase = macro_argbase; + } + else argbase = macrocurrent->args; +@@ -90,10 +97,11 @@ while (*p != 0) + { + if (p[1] == 0 || p[1] == '\n') error(30, "end of line", "$="); + else error(17, p[1], "$="); + *b++ = '$'; + *b++ = *p++; ++ blen -= 2; + continue; + } + while (isdigit(*(++p))) argn = argn * 10 + *p - '0'; + + if (*p == 0 || *p == '\n') +@@ -126,10 +134,11 @@ while (*p != 0) + if (!isdigit(p[1])) + { + if (*p == 0 || *p == '\n') error(30, "end of line", "$"); + else error(17, p[1], "$"); + *b++ = *p++; ++ blen--; + continue; + } + while (isdigit(*(++p))) argn = argn * 10 + *p - '0'; + + /* Handle $0 - currently no meaning */ +@@ -161,11 +170,16 @@ while (*p != 0) + } + } + + /* If we have found an argument, substitute it. */ + +- if (arg != NULL) b += sprintf(CS b, "%s", arg->string); ++ if (arg != NULL) ++ { ++ blen -= arg->length; ++ if (blen < 1) error(33); /* Hard; does not return */ ++ b += sprintf(CS b, "%s", arg->string); ++ } + } + + *b = 0; + } + +@@ -294,11 +308,12 @@ for (;;) + macrocurrent = macrocurrent->prev; + macro_free(temp); + } + else + { +- read_process_macroline(macrocurrent->nextline->string, inbuffer); ++ read_process_macroline(macrocurrent->nextline->string, inbuffer, ++ INBUFFSIZE); + macrocurrent->nextline = macrocurrent->nextline->next; + break; + } + } + +--- a/src/structs.h ++++ b/src/structs.h +@@ -42,10 +42,11 @@ typedef struct pushstr { + /* Macro content and argument item */ + + typedef struct argstr { + struct argstr *next; + uschar *string; ++ int length; + } argstr; + + /* Macro definition item */ + + typedef struct macrodef { +--- /dev/null ++++ b/testing/infiles/07 +@@ -0,0 +1,5 @@ ++.macro m1 one ++$1 ++.endmacro ++&m1(111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111) ++ +--- /dev/null ++++ b/testing/outfiles/07 +@@ -0,0 +1 @@ ++ +--- /dev/null ++++ b/testing/outfiles/07.err +@@ -0,0 +1,4 @@ ++** Error: maximum line length exceeded during macro substitution ++ Processing macro m1 ++ Detected near line 6 of infiles/07 ++** xfpt abandoned diff -Nru xfpt-0.11/debian/patches/series xfpt-0.11/debian/patches/series --- xfpt-0.11/debian/patches/series 2014-09-28 06:12:44.000000000 +0000 +++ xfpt-0.11/debian/patches/series 2024-10-19 11:32:57.000000000 +0000 @@ -1,2 +1,3 @@ 10_destdirsupport.diff 20_ld_and_cppflags.diff +30-Diagnose-error-if-macro-expansion-makes-a-line-too-l.patch