telepen_num: strcpy -> memcpy to ensure temp buffer filled (#270)

common: ensure stripf() not inlined to prevent optimizations undoing
  effect (#269), undo previous volatile temps workaround ([ac80b3])
This commit is contained in:
gitlost 2022-09-06 15:58:53 +01:00
parent ac80b33c3c
commit defb4587de
3 changed files with 46 additions and 41 deletions

View File

@ -488,10 +488,7 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height,
row_height = 0.5f; row_height = 0.5f;
} }
if (min_row_height) { if (min_row_height) {
/* This seems necessary to get gcc 12.2.1 to work consistently for static 32-bit builds */ if (stripf(row_height) < stripf(min_row_height)) {
volatile const float row_height_strip = stripf(row_height);
volatile const float min_row_height_strip = stripf(min_row_height);
if (row_height_strip < min_row_height_strip) {
error_number = ZINT_WARN_NONCOMPLIANT; error_number = ZINT_WARN_NONCOMPLIANT;
if (!no_errtxt) { if (!no_errtxt) {
strcpy(symbol->errtxt, "247: Height not compliant with standards"); strcpy(symbol->errtxt, "247: Height not compliant with standards");
@ -503,10 +500,7 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height,
symbol->height = stripf(fixed_height); /* Ignore any given height */ symbol->height = stripf(fixed_height); /* Ignore any given height */
} }
if (max_height) { if (max_height) {
/* See above */ if (stripf(symbol->height) > stripf(max_height)) {
volatile const float symbol_height_strip = stripf(symbol->height);
volatile const float max_height_strip = stripf(max_height);
if (symbol_height_strip > max_height_strip) {
error_number = ZINT_WARN_NONCOMPLIANT; error_number = ZINT_WARN_NONCOMPLIANT;
if (!no_errtxt) { if (!no_errtxt) {
strcpy(symbol->errtxt, "248: Height not compliant with standards"); strcpy(symbol->errtxt, "248: Height not compliant with standards");
@ -517,6 +511,13 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height,
return error_number; return error_number;
} }
/* Prevent inlining of `stripf()` which can optimize away its effect */
#if defined(__GNUC__) || defined(__clang__)
__attribute__((__noinline__))
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1310 /* MSVC 2003 (VC++ 7.1) */
__declspec(noinline)
#endif
/* Removes excess precision from floats - see https://stackoverflow.com/q/503436 */ /* Removes excess precision from floats - see https://stackoverflow.com/q/503436 */
INTERNAL float stripf(const float arg) { INTERNAL float stripf(const float arg) {
return *((volatile const float *) &arg); return *((volatile const float *) &arg);

View File

@ -34,7 +34,7 @@
/* Telepen Barcode Symbology information and History (BSiH) /* Telepen Barcode Symbology information and History (BSiH)
https://telepen.co.uk/wp-content/uploads/2018/10/Barcode-Symbology-information-and-History.pdf */ https://telepen.co.uk/wp-content/uploads/2018/10/Barcode-Symbology-information-and-History.pdf */
#define SODIUM_X_F (IS_NUM_F | IS_UX__F) /* SODIUM "0123456789X" */ #define SODIUM_X_F (IS_NUM_F | IS_UX__F | IS_LX__F) /* SODIUM "0123456789Xx" */
#include <stdio.h> #include <stdio.h>
#include "common.h" #include "common.h"
@ -155,7 +155,7 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int
int i; int i;
char dest[521]; /* 12 (start) + 30 * 16 (max for DELs) + 16 (check digit) + 12 (stop) + 1 = 521 */ char dest[521]; /* 12 (start) + 30 * 16 (max for DELs) + 16 (check digit) + 12 (stop) + 1 = 521 */
char *d = dest; char *d = dest;
unsigned char temp[64]; unsigned char temp[61];
count = 0; count = 0;
@ -163,20 +163,20 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int
strcpy(symbol->errtxt, "392: Input too long (60 character maximum)"); strcpy(symbol->errtxt, "392: Input too long (60 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
ustrcpy(temp, source); if (!is_sane(SODIUM_X_F, source, src_len)) {
to_upper(temp, src_len);
if (!is_sane(SODIUM_X_F, temp, src_len)) {
strcpy(symbol->errtxt, "393: Invalid character in data (digits and \"X\" only)"); strcpy(symbol->errtxt, "393: Invalid character in data (digits and \"X\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
/* Add a leading zero if required */ /* Add a leading zero if required */
if (src_len & 1) { if (src_len & 1) {
memmove(temp + 1, temp, src_len); memcpy(temp + 1, source, src_len++);
temp[0] = '0'; temp[0] = '0';
} else {
temp[++src_len] = '\0'; memcpy(temp, source, src_len);
} }
temp[src_len] = '\0';
to_upper(temp, src_len);
/* Start character */ /* Start character */
memcpy(d, TeleTable['_'], 12); memcpy(d, TeleTable['_'], 12);

View File

@ -27,6 +27,7 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. SUCH DAMAGE.
*/ */
/* SPDX-License-Identifier: BSD-3-Clause */
#include "testcommon.h" #include "testcommon.h"
@ -40,7 +41,7 @@ static void test_large(int index, int debug) {
int expected_rows; int expected_rows;
int expected_width; int expected_width;
}; };
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
struct item data[] = { struct item data[] = {
/* 0*/ { BARCODE_TELEPEN, "\177", 30, 0, 1, 528 }, /* 0*/ { BARCODE_TELEPEN, "\177", 30, 0, 1, 528 },
/* 1*/ { BARCODE_TELEPEN, "\177", 31, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 1*/ { BARCODE_TELEPEN, "\177", 31, ZINT_ERROR_TOO_LONG, -1, -1 },
@ -70,7 +71,7 @@ static void test_large(int index, int debug) {
ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length); ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
if (ret < 5) { if (ret < ZINT_ERROR) {
assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
} }
@ -90,7 +91,7 @@ static void test_hrt(int index, int debug) {
char *expected; char *expected;
}; };
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
struct item data[] = { struct item data[] = {
/* 0*/ { BARCODE_TELEPEN, "ABC1234.;$", -1, "ABC1234.;$" }, /* 0*/ { BARCODE_TELEPEN, "ABC1234.;$", -1, "ABC1234.;$" },
/* 1*/ { BARCODE_TELEPEN, "abc1234.;$", -1, "abc1234.;$" }, /* 1*/ { BARCODE_TELEPEN, "abc1234.;$", -1, "abc1234.;$" },
@ -98,8 +99,8 @@ static void test_hrt(int index, int debug) {
/* 3*/ { BARCODE_TELEPEN, "ABC\0001234", 8, "ABC 1234" }, /* 3*/ { BARCODE_TELEPEN, "ABC\0001234", 8, "ABC 1234" },
/* 4*/ { BARCODE_TELEPEN_NUM, "1234", -1, "1234" }, /* 4*/ { BARCODE_TELEPEN_NUM, "1234", -1, "1234" },
/* 5*/ { BARCODE_TELEPEN_NUM, "123X", -1, "123X" }, /* 5*/ { BARCODE_TELEPEN_NUM, "123X", -1, "123X" },
/* 6*/ { BARCODE_TELEPEN_NUM, "123x", -1, "123X" }, // Converts to upper /* 6*/ { BARCODE_TELEPEN_NUM, "123x", -1, "123X" }, /* Converts to upper */
/* 7*/ { BARCODE_TELEPEN_NUM, "12345", -1, "012345" }, // Adds leading zero if odd /* 7*/ { BARCODE_TELEPEN_NUM, "12345", -1, "012345" }, /* Adds leading zero if odd */
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
@ -137,7 +138,7 @@ static void test_input(int index, int debug) {
int expected_rows; int expected_rows;
int expected_width; int expected_width;
}; };
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
struct item data[] = { struct item data[] = {
/* 0*/ { BARCODE_TELEPEN, " !\"#$%&'()*+,-./0123456789:;<", -1, 0, 1, 512 }, /* 0*/ { BARCODE_TELEPEN, " !\"#$%&'()*+,-./0123456789:;<", -1, 0, 1, 512 },
/* 1*/ { BARCODE_TELEPEN, "AZaz\176\001", -1, 0, 1, 144 }, /* 1*/ { BARCODE_TELEPEN, "AZaz\176\001", -1, 0, 1, 144 },
@ -145,9 +146,9 @@ static void test_input(int index, int debug) {
/* 3*/ { BARCODE_TELEPEN, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 3*/ { BARCODE_TELEPEN, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 4*/ { BARCODE_TELEPEN_NUM, "1234567890", -1, 0, 1, 128 }, /* 4*/ { BARCODE_TELEPEN_NUM, "1234567890", -1, 0, 1, 128 },
/* 5*/ { BARCODE_TELEPEN_NUM, "123456789A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 5*/ { BARCODE_TELEPEN_NUM, "123456789A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 6*/ { BARCODE_TELEPEN_NUM, "123456789X", -1, 0, 1, 128 }, // [0-9]X allowed /* 6*/ { BARCODE_TELEPEN_NUM, "123456789X", -1, 0, 1, 128 }, /* [0-9]X allowed */
/* 7*/ { BARCODE_TELEPEN_NUM, "12345678X9", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // X[0-9] not allowed /* 7*/ { BARCODE_TELEPEN_NUM, "12345678X9", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* X[0-9] not allowed */
/* 8*/ { BARCODE_TELEPEN_NUM, "1X34567X9X", -1, 0, 1, 128 }, // [0-9]X allowed multiple times /* 8*/ { BARCODE_TELEPEN_NUM, "1X34567X9X", -1, 0, 1, 128 }, /* [0-9]X allowed multiple times */
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
@ -167,7 +168,7 @@ static void test_input(int index, int debug) {
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
if (ret < 5) { if (ret < ZINT_ERROR) {
assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
} }
@ -178,8 +179,10 @@ static void test_input(int index, int debug) {
testFinish(); testFinish();
} }
// Telepen Barcode Symbology information and History (BSiH) https://telepen.co.uk/wp-content/uploads/2018/10/Barcode-Symbology-information-and-History.pdf /* Telepen Barcode Symbology information and History (BSiH)
// E2326U: SB Telepen Barcode Fonts Guide Issue 2 (Apr 2009) https://telepen.co.uk/wp-content/uploads/2018/09/SB-Telepen-Barcode-Fonts-V2.pdf https://telepen.co.uk/wp-content/uploads/2018/10/Barcode-Symbology-information-and-History.pdf */
/* E2326U: SB Telepen Barcode Fonts Guide Issue 2 (Apr 2009)
https://telepen.co.uk/wp-content/uploads/2018/09/SB-Telepen-Barcode-Fonts-V2.pdf */
static void test_encode(int index, int generate, int debug) { static void test_encode(int index, int generate, int debug) {
struct item { struct item {
@ -233,7 +236,7 @@ static void test_encode(int index, int generate, int debug) {
char bwipp_buf[8192]; char bwipp_buf[8192];
char bwipp_msg[1024]; char bwipp_msg[1024];
int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */
testStart("test_encode"); testStart("test_encode");
@ -256,7 +259,7 @@ static void test_encode(int index, int generate, int debug) {
testUtilModulesPrint(symbol, " ", "\n"); testUtilModulesPrint(symbol, " ", "\n");
printf(" },\n"); printf(" },\n");
} else { } else {
if (ret < 5) { if (ret < ZINT_ERROR) {
int width, row; int width, row;
assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data);
@ -282,7 +285,7 @@ static void test_encode(int index, int generate, int debug) {
testFinish(); testFinish();
} }
// #181 Nico Gunkel OSS-Fuzz /* #181 Nico Gunkel OSS-Fuzz */
static void test_fuzz(int index, int debug) { static void test_fuzz(int index, int debug) {
struct item { struct item {
@ -291,16 +294,17 @@ static void test_fuzz(int index, int debug) {
int length; int length;
int ret; int ret;
}; };
// Note NULs where using DELs code (16 binary characters wide) /* Note NULs where using DELs code (16 binary characters wide) */
// s/\/\*[ 0-9]*\*\//\=printf("\/*%2d*\/", line(".") - line("'<")) /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
struct item data[] = { struct item data[] = {
/* 0*/ { BARCODE_TELEPEN, "\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", 30, 0 }, /* 0*/ { BARCODE_TELEPEN, "\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", 30, 0 },
/* 1*/ { BARCODE_TELEPEN, "\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", 31, ZINT_ERROR_TOO_LONG }, /* 1*/ { BARCODE_TELEPEN, "\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", 31, ZINT_ERROR_TOO_LONG },
/* 2*/ { BARCODE_TELEPEN_NUM, "\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\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 60, ZINT_ERROR_INVALID_DATA }, /* 2*/ { BARCODE_TELEPEN_NUM, "\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\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 60, ZINT_ERROR_INVALID_DATA },
/* 3*/ { BARCODE_TELEPEN_NUM, "040404040404040404040404040404040404040404040404040404040404", 60, 0 }, /* 3*/ { BARCODE_TELEPEN_NUM, "040404040404040404040404040404040404040404040404040404040404", 60, 0 },
/* 4*/ { BARCODE_TELEPEN_NUM, "1234567890123456789012345678901234567890123456789012345678901", 61, ZINT_ERROR_TOO_LONG }, /* 4*/ { BARCODE_TELEPEN_NUM, "1234567890123456789012345678901234567890123456789012345678901", 61, ZINT_ERROR_TOO_LONG },
/* 5*/ { BARCODE_TELEPEN_NUM, "00000000000000000000000000000000000000000000000000000000000X", 60, 0 }, /* 5*/ { BARCODE_TELEPEN_NUM, "00000000000000000000000000000000000000000000000000000000000X", 60, 0 },
/* 6*/ { BARCODE_TELEPEN_NUM, "999999999999999999999999999999999999999999999999999999999999", 60, 0 }, /* 6*/ { BARCODE_TELEPEN_NUM, "999999999999999999999999999999999999999999999999999999999999", 60, 0 },
/* 7*/ { BARCODE_TELEPEN_NUM, "1234567890123456789012345678901234567890123456789012345678901234567890", 4, 0 }, /* Length given, strlen > 61, so pseudo not NUL-terminated */
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
@ -365,7 +369,7 @@ static const char TeleTable[128][16] = {
{'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'}, {'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'},
}; };
// Dummy to generate lengths table /* Dummy to generate lengths table */
static void test_generate_lens(int generate) { static void test_generate_lens(int generate) {
int i; int i;