Skip to content

Fix Code128 build() producing different output on repeated calls#264

Open
apoorvdarshan wants to merge 1 commit into
WhyNotHugo:mainfrom
apoorvdarshan:fix/issue-143-code128-repeated-build
Open

Fix Code128 build() producing different output on repeated calls#264
apoorvdarshan wants to merge 1 commit into
WhyNotHugo:mainfrom
apoorvdarshan:fix/issue-143-code128-repeated-build

Conversation

@apoorvdarshan

Copy link
Copy Markdown

Fixes #143

Root cause

Code128._build mutates self._charset and self._digit_buffer while it walks the code (switching charsets via _new_charset, buffering digit pairs in charset C). Both attributes are initialised only once, in __init__. When a build ends in charset A/B — or with a digit still buffered — those attributes are left in a "dirty" state. The next call to build() / encoded starts from that stale state instead of the intended _charset = "C" / empty buffer, so it emits a different (and incorrect) bit string.

Reproduction

from barcode import Code128

inst = Code128("12A")
for _ in range(3):
    print(inst.build()[0])

Observed (before the fix) — the first call is correct, later calls diverge:

11010011100101100111001011110111010100011000100100011001100011101011
11010010000100111001101100111001010100011000110001011101100011101011
11010010000100111001101100111001010100011000110001011101100011101011

The divergence is the start code: the first build begins in charset C (START_C = 105); after it the instance is left in charset B, so later builds begin with START_B = 104. A freshly constructed Code128("12A") always reproduces the first (correct) line, confirming the later output is the buggy one.

After the fix every call returns the same, correct value:

11010011100101100111001011110111010100011000100100011001100011101011
11010011100101100111001011110111010100011000100100011001100011101011
11010011100101100111001011110111010100011000100100011001100011101011

The original report's all-digit example (Code128("1170773")) never left charset C, so it happened to be stable on current main; inputs that switch charset (e.g. "12A", "123ABC456") expose the bug.

Fix

Reset self._charset = "C" and self._digit_buffer = "" at the start of _build(), so each build begins from the same initial state regardless of what the previous one left behind. This is the smallest localized change and touches only the entry of _build.

Tests

Added tests/test_code128.py with three regression tests asserting that repeated build() / encoded calls on one instance are deterministic and that a reused instance matches a freshly constructed one. These tests fail on unmodified main and pass with the fix. The full existing suite (52 tests, including the GS1-128 charset-C build tests) continues to pass, and ruff check / ruff format --check are clean.

Disclosure: prepared with AI assistance; reviewed and verified locally.

Code128._build mutated self._charset and self._digit_buffer (both set
only in __init__) but never reset them. After a build that switched to
charset A/B or left a digit buffered, a subsequent build()/encoded call
started from stale state and emitted a different, incorrect bit string.

Reset both to their initial values at the start of _build() so repeated
calls on the same instance are deterministic.

Fixes WhyNotHugo#143
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build() brings different results on repeated calls

1 participant