Make barcode bad fixture self-contained: 1D EncodeFont without ValidateInput

The previous bad fixture (literal '*' delimiters, no layout/font/provider
evidence) no longer matched the narrowed routing cue. It now shows an
IDAutomation 1D provider path that calls EncodeFont without ValidateInput,
which is visible in AL alone. Article Anti Pattern and Source updated to
describe this variant (verified: IDAutomation 1D Provider's EncodeFont
does not call IsValidInput).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Michael Dieringer 2026-09-28 18:02:08 +02:00
parent e246b1942a
commit 4cd41f08f7
2 changed files with 29 additions and 20 deletions

View file

@ -12,30 +12,30 @@ report 50110 "Sample Item Barcode Label"
column(Barcode; BarcodeText) { }
trigger OnAfterGetRecord()
var
BarcodeFontProvider: Interface "Barcode Font Provider";
begin
// WRONG: hand-rolled "encoding" instead of the Barcode
// module's provider/encoder API. This is not wrong merely
// because the delimiter was added by hand - Code 39's own
// symbology does use "*" as its start/stop character
// (Microsoft Learn, "Barcode Fonts with Business Central
// Online"). It's wrong because it's demonstrably mismatched
// with what encoding "No." through the real API would
// produce:
// - it skips ValidateInput, so a "No." value outside Code
// 39's character set, or one that needs a checksum this
// code never applies, reaches the font unvalidated;
// - IDAutomation 1D Provider's own EncodeFont output for
// Code 39 wraps the value in "(" / ")", not literal "*"
// (BCApps' own encoder test: EncodeFont('1234', Code39)
// = '(1234)') - the paired font maps those parentheses to
// the real start/stop glyph, so a string built with
// literal asterisks is simply the wrong characters for
// that font, on top of carrying no real checksum.
BarcodeText := '*' + "No." + '*';
// WRONG: a one-dimensional IDAutomation provider path that
// calls EncodeFont without ValidateInput. "Barcode Font
// Provider" (1D) declares both, and IDAutomation 1D
// Provider's EncodeFont does not validate on its own - it
// hands the text straight to the font encoder. Code 39
// accepts only 0-9, A-Z, space and - . $ / + % *, but an
// Item "No." can legally contain characters outside that
// set (e.g. "_" or "#"). Such a value is never rejected;
// it silently reaches the font as an unscannable barcode.
BarcodeFontProvider := Enum::"Barcode Font Provider"::IDAutomation1D;
BarcodeText := BarcodeFontProvider.EncodeFont("No.", BarcodeSymbology);
end;
}
}
var
BarcodeSymbology: Enum "Barcode Symbology";
BarcodeText: Text;
trigger OnInitReport()
begin
BarcodeSymbology := Enum::"Barcode Symbology"::Code39;
end;
}

View file

@ -78,13 +78,22 @@ evaluation font instead of the purchased one. Both look complete in
review and fail silently — the first because the data was never a real
barcode, the second because BC online refuses to render it.
The same gap exists even when the module *is* used: a 1D path that calls
`EncodeFont` on `"Barcode Font Provider"` without `ValidateInput`.
IDAutomation 1D Provider's `EncodeFont` does not validate on its own, so
a value outside the symbology's character set is never rejected — it
reaches the font as an unscannable barcode. The sample shows this
variant, because it is visible in AL alone without layout evidence.
See sample: [`report-barcodes-must-use-barcode-module-and-production-font-name.bad.al`](report-barcodes-must-use-barcode-module-and-production-font-name.bad.al).
## Source
BCApps (`src/System Application/App/Barcode/src/`):
`Barcode Provider/Font/BarcodeFontProvider.Interface.al` (1D:
`ValidateInput` + `EncodeFont`); `Barcode Provider 2D/Font/
`ValidateInput` + `EncodeFont`); `IDAutomation 1D Provider/
IDAutomation1DProvider.Codeunit.al` (`EncodeFont` goes straight to the
symbology encoder; only `ValidateInput` calls `IsValidInput`); `Barcode Provider 2D/Font/
BarcodeFontProvider2D.Interface.al` (2D: only `EncodeFont`); both read
fresh from source. `IDAutomation 1D Provider/Encoders/
IDA1DCode39Encoder.Codeunit.al` (`codeunit 9204`, regex accepts literal