QXmlSimpleReader: add parameter entity length checks


The earlier patches fixed the size checks for the expansion of general
entities.

However, the parser also processes parameter entities.
While the W3C spec forbids referencing parameter entities from
general entities or from other parameter entities in the internal
subset of DTD, the QXmlSimpleReader's parser historically allows
it.

We can try to follow the specification, and thus change the
behavior, or just introduce the same entitiy expanstion limits,
as applied to the general entities. I chose the second approach.

Parameter entities are expanded in two places in parsePEReference(),
and each of them needs a limit.
1. A parameter entity included in the DTD.
   Its replacement text is parsed again, so it can contain further
   parameter entity references, and general entity references in
   default attribute values of ATTLIST declarations. A parameter
   entity reference can even be created with "%", which becomes a
   plain '%' when the entity value is declared, and is only recognized
   as a reference once the value is included in the DTD.
   Handle it exactly like general entities: count the size in
   insertXmlRef(). An internal parameter entity included in the DTD
   starts the count of the outermost expansion, or continues it, and
   every parameter or general entity expanded while it is on the
   reference stack adds to the same counter. Replace the boolean
   parameter of insertXmlRef() with an ExpansionCheck enum, so that
   parameter entities can be reported with the '%' prefix in the error
   message.
2. A parameter entity included in an entity value.
   Here the thing that needs to be limited is the value that is being
   built, not a single reference. That value is read from the
   document, not from the reference stack, and each included parameter
   entity is popped from the stack before the next reference is read.
   The counter used for the expansions would therefore treat every
   sibling reference in
     <!ENTITY % b '%a;%a;%a;...'>
   as a new outermost expansion, and restart counting each time.
   Add a separate includedParameterEntitySize counter that sums up the
   sizes of all parameter entities included in the entity value that is
   currently being parsed, and reset it at the start of every entity
   value.

Note that the first check will technically catch both cases. However,
it does not prevent the problem of a potentially uncontrolled expansion
of nested parameter entities - that's what the second check catches.

This fixes the remaining failing cases of the entityExpansionLimit()
test. Also new test cases are added:
* parameter_entity_run_in_DTD_huge_expansion makes sure that the
  entity value is limited while it is being built, and not only after
  the full expansion;
* entity_refs_in_parameter_entity verifies that general entity
  references in a parameter entity are only expanded (and limited)
  once the general entity that includes it is used in the document;
* parameter_entity_char_ref_in_DTD and
  general_entity_in_parameter_entity_in_DTD cover the expansions of a
  parameter entity included in the DTD.

Task-number: QTBUG-149213
Pick-to: 6.12 6.8 6.5 5.15
Change-Id: I173ddf67fd028c665ecbd1c58e4c4abf659e08db
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
commit039d8e1ef3e7e5b23924bcfa725bd80d6368e0ab
parentb79352273c9a841efeddfa768646f0cc9e378a4d
authorIvan Solovev <ivan.solovev@qt.io>
committerIvan Solovev <ivan.solovev@qt.io>
commit timeMon, 19 Oct 2026 18:34:04 +0000