From 4b57fb80218c4799ab0c5af0ad70704e12692b73 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 21 Nov 2023 22:39:07 +0000 Subject: [PATCH] PDF417: fix out-of-bounds crash in `pdf_text_submode_length()` by changing `pdf_num_stay()` to not call it if previous/next block is BYT; also extend `pdf_asciix[]` to full 256 byte range (defensive & also can use directly rather than checking range, ticket #300, props Andre Maute --- ChangeLog | 2 ++ backend/pdf417.c | 27 +++++++++++++++++---------- backend/tests/test_pdf417.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 22d1ebc6..68647d32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -109,6 +109,8 @@ Bugs - GUI: fix not enabling font combo "Small Bold (vector only)" by default - CODEONE: fix S/T quiet zone 1X bottom (props BWIPP issue #245 doc) - EAN-2/EAN-5: fix `BARCODE_BIND_TOP/BIND/BOX` output +- PDF417: fix out-of-bounds crash in `pdf_text_submode_length()`, ticket #300, + props Andre Maute Version 2.12.0 (2022-12-12) diff --git a/backend/pdf417.c b/backend/pdf417.c index 4d6b5f28..76716459 100644 --- a/backend/pdf417.c +++ b/backend/pdf417.c @@ -93,7 +93,7 @@ static const char *pdf_mode_str(const int mode) { /* text mode processing tables */ /* TEX sub-mode assignments */ -static const char pdf_asciix[127] = { +static const char pdf_asciix[256] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 00-07 */ 0, T_MXPNC, T_PUNCT, 0, 0, T_MXPNC, 0, 0, /* 08-0F ..... */ 0, 0, 0, 0, 0, 0, 0, 0, /* 10-17 */ @@ -109,7 +109,11 @@ static const char pdf_asciix[127] = { T_PUNCT, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, /* 60-67 `abcdefg */ T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, /* 68-6F hijklmno */ T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, T_LOWER, /* 70-77 pqrstuvw */ - T_LOWER, T_LOWER, T_LOWER, T_PUNCT, T_PUNCT, T_PUNCT, T_PUNCT /* 78-7E xyz{|}~ */ + T_LOWER, T_LOWER, T_LOWER, T_PUNCT, T_PUNCT, T_PUNCT, T_PUNCT, 0, /* 78-7E xyz{|}~D */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80-9F*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*A0-BF*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*C0-DF*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*E0-FF*/ }; /* TEX sub-mode values */ @@ -152,7 +156,7 @@ static int pdf_quelmode(const unsigned char codeascii) { if (z_isdigit(codeascii)) { return PDF_NUM; } - if (codeascii < 127 && pdf_asciix[codeascii]) { + if (pdf_asciix[codeascii]) { return PDF_TEX; } /* 876 */ @@ -233,6 +237,7 @@ static int pdf_text_submode_length(const unsigned char chaine[], const int start int j, indexlistet, curtable = *p_curtable, listet[PDF_MAX_LEN], chainet[PDF_MAX_LEN], wnet = 0; for (indexlistet = 0; indexlistet < length; indexlistet++) { + assert(pdf_asciix[chaine[start + indexlistet]]); /* Should only be dealing with TEX */ listet[indexlistet] = pdf_asciix[chaine[start + indexlistet]]; } @@ -283,7 +288,7 @@ static int pdf_text_submode_length(const unsigned char chaine[], const int start /* Whether to stay in numeric mode or not */ static int pdf_num_stay(const unsigned char *chaine, const int indexliste, int liste[3][PDF_MAX_LEN], const int i) { - int curtable, last_len, last_ml, next_len, num_cws, tex_cws; + int curtable, not_tex, last_len, last_ml, next_len, num_cws, tex_cws; if (liste[0][i] >= 13 || (indexliste == 1 && liste[0][i] > 5)) { return 1; @@ -293,15 +298,17 @@ static int pdf_num_stay(const unsigned char *chaine, const int indexliste, int l } curtable = T_ALPHA; - last_len = i == 0 ? 0 : pdf_text_submode_length(chaine, liste[2][i - 1], liste[0][i - 1], &curtable); + not_tex = i == 0 || liste[1][i - 1] == PDF_BYT; + last_len = not_tex ? 0 : pdf_text_submode_length(chaine, liste[2][i - 1], liste[0][i - 1], &curtable); last_ml = curtable == T_MIXED; curtable = T_ALPHA; /* Next len if after NUM, sub-mode will be alpha */ - next_len = i == indexliste - 1 ? 0 : pdf_text_submode_length(chaine, liste[2][i + 1], liste[0][i + 1], &curtable); + not_tex = i == indexliste - 1 || liste[1][i + 1] == PDF_BYT; + next_len = not_tex ? 0 : pdf_text_submode_length(chaine, liste[2][i + 1], liste[0][i + 1], &curtable); num_cws = ((last_len + 1) >> 1) + 1 + 4 + (liste[0][i] > 11) + 1 + ((next_len + 1) >> 1); curtable = T_MIXED; /* Next len if stay TEX, sub-mode will be mixed */ - next_len = i == indexliste - 1 ? 0 : pdf_text_submode_length(chaine, liste[2][i + 1], liste[0][i + 1], &curtable); + next_len = not_tex ? 0 : pdf_text_submode_length(chaine, liste[2][i + 1], liste[0][i + 1], &curtable); tex_cws = (last_len + !last_ml + liste[0][i] + next_len + 1) >> 1; if (num_cws > tex_cws) { @@ -505,7 +512,7 @@ static void pdf_textprocess_minimal(int *chainemc, int *p_mclength, const unsign const int from = liste[2][i]; for (j = 0; j < liste[0][i]; j++) { const int c = chaine[from + j]; - const int t_table = c < 127 ? pdf_asciix[c] : 0; + const int t_table = pdf_asciix[c]; if (!t_table) { /* BYT Shift? */ if (wnet & 1) { chainet[wnet++] = 29; /* PS or AL (T_PUNCT) */ @@ -665,7 +672,7 @@ INTERNAL void pdf_numbprocess_test(int *chainemc, int *p_mclength, const unsigne static int pdf_table_length(const unsigned char source[], const int length, const int position, const int t_table) { int i; - for (i = position; i < length && source[i] < 127 && (pdf_asciix[source[i]] & t_table); i++); + for (i = position; i < length && (pdf_asciix[source[i]] & t_table); i++); return i - position; } @@ -857,7 +864,7 @@ static void pdf_addEdge(const unsigned char *source, const int length, struct pd static void pdf_addEdges(const unsigned char source[], const int length, const int lastmode, struct pdf_edge *edges, const int from, struct pdf_edge *previous) { const unsigned char c = source[from]; - const int t_table = c < 127 ? pdf_asciix[c] : 0; + const int t_table = pdf_asciix[c]; if (t_table & T_ALPHA) { const int len = pdf_table_length(source, length, from, T_ALPHA); diff --git a/backend/tests/test_pdf417.c b/backend/tests/test_pdf417.c index 65fddd9e..3559b8b2 100644 --- a/backend/tests/test_pdf417.c +++ b/backend/tests/test_pdf417.c @@ -4775,7 +4775,7 @@ static void test_encode_segs(const testCtx *const p_ctx) { testFinish(); } -/* #181 Nico Gunkel OSS-Fuzz */ +/* #181 Nico Gunkel OSS-Fuzz and #300 Andre Maute */ static void test_fuzz(const testCtx *const p_ctx) { int debug = p_ctx->debug; @@ -5296,6 +5296,35 @@ static void test_fuzz(const testCtx *const p_ctx) { "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ", 251, -1, ZINT_ERROR_TOO_LONG }, + /*28*/ { BARCODE_PDF417COMP, DATA_MODE | FAST_MODE, + "\000\000\000\377\377\010\002\000\000\033\005\031\000\000\002\000\000\000\000\101\101\101\101\101\101\101\101\000\000\000\000\000\000\000\374\000\101\101\101\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\323\000\000\000\000\000\010\000\000\000\000\165\000\000\000\000\000\000\000\000\000\000\000\000\056" + "\000\000\000\000\000\000\000\000\000\000\100\000\000\101\101\101\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\323\000\000\000\000\000\010\000" + "\000\000\000\000\000\000\000\000\000\000\000\323\000\000\000\000\000\010\000\000\000\000\165\000\000\000\000\000\000\000\000\000\000\000\000\056\000\000\000\000" + "\000\000\000\000\000\000\000\000\101\101\101\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\323\000\010\000\000\000\010\000\000\000\000\165\000" + "\000\000\000\000\000\000\000\000\000\000\000\056\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\377\377\377\377\377\377\375\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\101\101\101\101\101\101\101\101\101\101\101\055\101\101\101\101\101\101\101\101\101" + "\101\101\101\060\151\003\000\000\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\137\101\101\101\101\101\101\101\101\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\101\101\101\101\101\101\101\101\101\101\000\000\000\000\000\000\000\000\000\070\000\000\000\000\000\000\000" + "\000\000\000\377\377\010\002\000\000\033\005\031\000\000\002\000\000\000\000\101\101\101\101\101\101\101\101\000\000\000\000\000\000\000\374\000\101\101\101\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\323\000\000\000\000\000\010\000\000\000\000\165\000\000\000\000\000\000\000\000\000\000\000\000\056" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\377\377\377\377\377\377\375\000\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\377\377\377\377\377\377\375\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\101\101\101\101\101\101\101\101\101\101\101\101\101\055\101\101\101\101\101\101\101\101\101" + "\101\101\101\060\151\003\000\000\101\101\101\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\373\377\377\377\377\060" + "\060\060\060\060\060\060\060\060\060\060\060\051\060\060\060\060\060\060\377\377\377\377\000\000\000\000\377\161\000\151\151\250\122\141\012\377\377\021\021\021" + "\021\021\021\161\021\000\324\324\324\324\324\324\324\324\324\324\324\000\000\000\000\112\000\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324" + "\320\324\324\324\324\021\176\012\000\000\000\000\000\000\324\324\324\324\324\324\324\101\101\101\101\101\101\101\352\352\352\352\352\352\352\352\352\352\352\352" + "\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\352\000" + "\000\000\000\000\101\101\101\101\101\101\101\101\101\101\101\101\101\137\101\101\101\101\101\101\101\101\000\000\000\000\000\000\000\000\000\000\000\000\101\101" + "\101\101\041\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\324\324\324\324\324\324\324\324\324\077\324\324\324\324\324\324\324\324\324\324" + "\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\324\000\060\060\060\060\060" + "\060\060\060\060\060\060\060\060\060\060\060\051\060\060\060\060\060\060\377\377\377\377\000\000\000\000\377\161\000\151\151\250\122\141\012\377\377\021\021\021" + "\021\021\021\161\021\000\324\324\324\324\324\324\324\324\324\324\324\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\101\137\101\101\101\101\101" + "\101\000\000\000\000\374\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\323\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\323\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000", + 1048, 0, 0 }, /* #300 Andre Maute */ }; int data_size = ARRAY_SIZE(data); int i, length, ret;