Merge String Constant

The `CALCIUM` "name" is a macro which expands to a string constant.

Referencing the macro twice will cause it to be expanded twice, resulting
in two string instances which have identical content. By default, gcc will
deduplicate these two strings into the same memory region as gcc detects
the duplicated constant, even when optimization turned off (see
-fmerge-constants and -fmerge-all-constants GCC options).

The C Language specification does not require duplicated constants to be
deduplicated, and, in fact, the GCC manual page also explicitly states
this optimization is not performed for all targets.

Visual C++, in debug mode, does not deduplicate constants. This results
in `count += strchr(CALCIUM,x) - CALCIUM` yielding to negative values as
the substracted CALCIUM's expansion resides on a greater memory address
then the memory allocated for the expansion passed to `strchr`. The
value of `count` is used to compute the checksum, which then is not only
faulty, but also used as an array index without previously checking
whether or not the index is within the array bounds (modulo of a negative
integer is negative, which means out of bounds). This will cause very
difficult to predict behavior, in most cases, however, it will cause a
segmentation fault.

Manually allocate a memory range to contain the string, and use
this range instead of expanding the macro multiple times.
This commit is contained in:
Schaich 2021-06-09 22:37:16 +09:00
parent 4a8cac2a5a
commit e7947dc9a4

View File

@ -236,8 +236,9 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len
add_checksum = symbol->option_2 == 1; add_checksum = symbol->option_2 == 1;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
const char calcium[] = CALCIUM;
if (add_checksum) { if (add_checksum) {
count += strchr(CALCIUM, source[i]) - CALCIUM; count += strchr(calcium, source[i]) - calcium;
if (i + 1 == length) { if (i + 1 == length) {
checksum = count % 16; checksum = count % 16;
if (checksum) { if (checksum) {
@ -249,7 +250,7 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len
strcat(dest, CodaTable[checksum]); strcat(dest, CodaTable[checksum]);
} }
} }
lookup(CALCIUM, CodaTable, source[i], dest); lookup(calcium, CodaTable, source[i], dest);
} }
expand(symbol, dest); expand(symbol, dest);