zplCore.comzplCore.com

37Limits for untrusted input & thread safety

Labels from uploads, web services, ERP interfaces or coding agents are untrusted input. zplCore limits what such input may cost – labels, dots, graphics, field data, printer storage, image files – and documents which classes may be shared between threads.

Related: the security model of the MCP server runs every call inside these limits; the licence check works offline, without any network access.

ZplLimits: one scope for everything

For untrusted input (uploads, web services, agents) ZplLimits.Enforce sets hard limits for every renderer in its scope – also those that the compliance check, scan-proof, import, extraction, GS1 migration, printer twin, cut plan and Vector-Lift create internally, across tasks and Parallel loops. Settings are clamped to the stricter value, font providers, system fonts and background images are turned off; optionally a fixed clock. The MCP server runs every call inside this scope.

// using ZplCore.Compliance;

using (ZplLimits.Enforce(new ZplLimits { MaxLabels = 10, MaxGraphicBytes = 4 << 20, FixedClock = DateTime.UnixEpoch }))
{
    // applies to every renderer in this scope – also those that compliance, scan-proof,
    // import, extraction, printer twin and Vector-Lift create internally (also across tasks/Parallel)
    var report = ZplCompliance.Check(untrusted, CompliancePacks.Gs1LogisticLabel);
}

Images and files: inside a scope, image items (sourceFile or a path in bound data) read no local files unless they lie below one of the AllowedImageRoots (default: none; no links below the root) – a refused, missing or unreadable file always gives the same answer, so no path can be probed. Images are checked before decoding against MaxImageBytes, MaxSvgBytes and MaxImagePixels (header size, SVG raster and scaled target raster; exceeding throws ZplLimitExceededException). A CancellationToken stops rendering and label generation at the next command or label, so a host can end work at its time limit. Outside a scope nothing changes: the SDK reads image files as before.

using (ZplLimits.Enforce(new ZplLimits { AllowedImageRoots = ["/srv/label-images"], MaxImagePixels = 16_000_000,
    MaxImageBytes = 4 << 20, CancellationToken = requestTimeout.Token }))
    zpl = label.ToZpl(records);

Further members: MaxQuantity, MaxLabelDots, MaxLabelSide, MaxFieldDataLength, MaxStoreBytes (printer storage) and Isolated (default true: no FontProvider, no system fonts, no background or watermark image, no cache of decoded graphics – fonts then come only from downloads in the same input, ~DY/~DU). A limit that is not set is unlimited; nested scopes combine to the strictest values (image folders: only what every scope allows; any token cancels). ZplLimits.Current returns the limits in force, ZplLimitExceededException.Limit names the exceeded property, e.g. "MaxImagePixels".

Limits for untrusted input & thread safety

Defaults: MaxLabelSide 32000, MaxLabelDots 64 million, MaxQuantity 10000, MaxLabels 100000, MaxGraphicBytes 32 MB (also the Z64 decompression limit against zip bombs), MaxFieldDataLength 1 million, ZplResourceStore.MaxTotalBytes 256 MB. ZplRenderer/EplRenderer hold printer state and are not thread-safe – use one renderer per thread; ZplResourceStore, FontManager, ZplCaches, PropertyPath and configured LabelBindings are. ConcurrencyTests compares the SHA-256 of all outputs from 16 threads with the single-threaded run; samples/FuzzRunner feeds the parser random and mutated input, samples/LeakTest renders 1 million labels and logs heap and RSS. Details: THREADING.md, DIAGNOSTICS.md.

var shared = new ZplResourceStore();                          // thread-safe, shareable by many renderers
var safe = new ZplRenderSettings
{
    MaxLabelSide = 8000, MaxLabelDots = 16_000_000, MaxQuantity = 100,
    MaxLabels = 1000, MaxGraphicBytes = 4 * 1024 * 1024, MaxFieldDataLength = 10_000,
};
Parallel.For(0, 8, _ =>
{
    var r = new ZplRenderer(safe) { Store = shared };         // one renderer per thread
    r.ProcessCommands(untrusted);
});

zplCore.com – independent implementation based on the public ZPL II specification. Barcode encoders partly derived from BWIPP/bwip-js (MIT) and zint (BSD-3); Roboto Condensed (OFL) and DejaVu fonts under their own licenses – see THIRD-PARTY-NOTICES.md. ZPL and Zebra are trademarks of Zebra Technologies.

Zebra, ZPL, ZPL II, EPL and Link-OS are trademarks or registered trademarks of Zebra Technologies Corp. QR Code is a registered trademark of DENSO WAVE INCORPORATED. GS1, GS1 DataBar, GS1 Digital Link, EPC and EPCglobal are trademarks of GS1 AISBL. ESC/POS is a registered trademark of Seiko Epson Corporation, Intelligent Mail a registered trademark of the United States Postal Service and Mailmark a registered trademark of Royal Mail Group Ltd. Other product and company names and logos mentioned are trademarks or registered trademarks of their respective owners. We use these names only to describe compatibility with file formats, printer languages and standards. zplCore.com is an independent product and is not endorsed, sponsored or certified by these companies; compliance packs are pre-checks, not certifications.