Skip to content

QA Report: XML Parser #2387

Description

@xsscx

QA Summary for XML Parsing

2026-09-04 02:44:19 UTC
Edited by @xsscx

Codex Report

Finding 1: ProfileVersion sub-class components lose leading digits

At IccProfileXml.cpp:473-486, the third and fourth component loops assign ver = *szVer instead of appending with ver += *szVer. Therefore only the last digit of each component reaches the otherwise strict parseVersion helper.

The fixture requests 5.10.12.34. iccFromXml exits zero and says it saved the profile correctly. iccDumpProfile and iccToXml both report 5.10.2.04.

Specs

  • ICC.2:2023 section 7.2.6, PDF page 19, requires bytes 8 through 11 to encode the profile and sub-class versions as binary-coded decimal. Byte 10 is sub-class major and byte 11 is sub-class minor
  • ICC.2:2023 section 7.2.17, PDF page 24, defines only Perceptual (0), media-relative colorimetric (1), Saturation (2), and ICC-absolute colorimetric (3) for the rendering intent field

PoC

<?xml version="1.0" encoding="UTF-8"?>
<IccProfile>
  <Header>
    <ProfileVersion>5.10.12.34</ProfileVersion>
    <ProfileDeviceClass>cenc</ProfileDeviceClass>
    <ProfileDeviceSubClass>test</ProfileDeviceSubClass>
    <DataColourSpace>RGB </DataColourSpace>
  </Header>
  <Tags>
    <utf8TextType>
      <TagSignature>rfnm</TagSignature>
      <TextData>QA four-component profile version</TextData>
    </utf8TextType>
  </Tags>
</IccProfile>

CLI Repro

iccFromXml foo.xml foo.icc

Incorrect Output

iccDumpProfile foo.bar | grep -E 'Version:|SubClass Version:'
Version:            5.10
SubClass Version:   2.04

Expected Output

Expected: Profile Version 5.10 and SubClass Version 12.34.

Finding 2: explicit ProfileSubClassVersion is parsed as last-digit.00

PoC

<?xml version="1.0" encoding="UTF-8"?>
<IccProfile>
  <Header>
    <ProfileVersion>5.10</ProfileVersion>
    <ProfileDeviceClass>cenc</ProfileDeviceClass>
    <ProfileDeviceSubClass>test</ProfileDeviceSubClass>
    <ProfileSubClassVersion>12.34</ProfileSubClassVersion>
    <DataColourSpace>RGB </DataColourSpace>
  </Header>
  <Tags>
    <utf8TextType>
      <TagSignature>rfnm</TagSignature>
      <TextData>QA explicit profile subclass version</TextData>
    </utf8TextType>
  </Tags>
</IccProfile>

At IccProfileXml.cpp:513-526, the major loop also assigns rather than appends. After that loop stops at the separator, the code does not advance szVer. The minor loop consequently executes zero times and atoi("") supplies zero. This path also bypasses parseVersion and its digit/range checks.

The fixture requests 12.34. The tool exits zero and the ICC and round-trip XML contain 2.00.

Finding 3: unknown RenderingIntent silently becomes Perceptual

PoC

<?xml version="1.0" encoding="UTF-8"?>
<IccProfile>
  <Header>
    <ProfileVersion>5.10</ProfileVersion>
    <ProfileDeviceClass>cenc</ProfileDeviceClass>
    <DataColourSpace>RGB </DataColourSpace>
    <RenderingIntent>Typographical Error</RenderingIntent>
  </Header>
  <Tags>
    <utf8TextType>
      <TagSignature>rfnm</TagSignature>
      <TextData>QA unknown rendering intent</TextData>
    </utf8TextType>
  </Tags>
</IccProfile>

At IccProfileXml.cpp:593-606, four recognized strings assign a value, but an unknown non-empty string has no rejecting else branch. ParseBasic zeroes the header at line 436, so the unassigned enum remains zero, which is Perceptual.

The fixture supplies Typographical Error. The tool exits zero, reports a correct save, and the ICC and round-trip XML report Perceptual.

Finding 4: malformed ProfileVersion is saved and exits zero

PoC

?xml version="1.0" encoding="UTF-8"?>
<IccProfile>
  <Header>
    <ProfileVersion>5.x</ProfileVersion>
    <ProfileDeviceClass>cenc</ProfileDeviceClass>
    <DataColourSpace>RGB </DataColourSpace>
  </Header>
  <Tags>
    <utf8TextType>
      <TagSignature>rfnm</TagSignature>
      <TextData>QA malformed profile version</TextData>
    </utf8TextType>
  </Tags>
</IccProfile>

The issue #1845 repair made parseVersion strict. On failure, IccProfileXml.cpp:492-499 appends a reason and leaves version zero, but ParseBasic returns true at line 704. IccFromXml.cpp prints the parse reason only when LoadXml returns false (lines 77-84). It then deliberately saves profiles whose profile validation is worse than warning (lines 101-117) and returns EXIT_SUCCESS.

With 5.x, the tool says only that an invalid profile was saved, emits the downstream ColorEncoding/version error, writes version 0.00, and exits zero. The useful Cannot parse ProfileVersion '5.x' reason is suppressed.

Finding 5: bare -v fails open when its schema is absent

IccFromXml.cpp:45-73 searches for SampleIccRELAX.rng. If fopen fails, it leaves the schema string empty without a diagnostic. LoadXml validates only when that string is non-empty (IccProfileXml.cpp:1062). The reviewed build directory does not contain SampleIccRELAX.rng, so bare -v is behaviorally identical to no -v. Supplying an explicit reject-all schema correctly rejects the same document with exit 1 and no ICC output.

Activity

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

Metadata

Metadata

Labels

CodexCodex use indicated by MaintainerQAMaintainer indicates topic of Quality AssuranceSpecICC specification, tag, color-space, or schema scopeTriagedMaintainer indicates triaged status and ready for developer handoffgpt-6-astraMaintainer indicates use of Codex gpt-6-astra ModelpawgMaintainer indicates subject matter with spected to Profile Assessment Working Group (PAWG)

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions