Skip to content

Encoder hardening - #102

Open
alexejk wants to merge 2 commits into
time-formatsfrom
encoder-hardening
Open

Encoder hardening#102
alexejk wants to merge 2 commits into
time-formatsfrom
encoder-hardening

Conversation

@alexejk

@alexejk alexejk commented Aug 31, 2026

Copy link
Copy Markdown
Owner

This PR fixes a couple of encoder defects

Malformed XML from unescaped names.

Method names, struct member names (including xmlrpc tags) and map keys were written raw, so any & or < produced a document the server can't parse. Map keys are the sharpest case, since they can carry data from outside the program.

Silent precision loss on doubles.

%f pads to six decimals and drops the rest: 0.1234567890123 went out as 0.123457, and both 1e-10 and 1e-300 became 0.000000. Values now use the shortest representation that round-trips exactly — no exponent, always a decimal point, per the spec's grammar. NaN and infinities have no representation in the spec and are now rejected rather than emitted as NaN/+Inf.

Output goes through a small xmlWriter utility that escapes character data and latches the first write error. Previously most writes discarded their error, so a failing writer could return nil from Encode with a truncated request already sent.

Public API unchanged. Wire format change: doubles are shorter (3.14, not 3.140000) - same values, fewer digits.


Stack created with GitHub Stacks CLIGive Feedback 💬

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.64706% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
encode.go 97.33% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@alexejk
alexejk force-pushed the encoder-hardening branch from dcfb8e3 to d208e34 Compare August 31, 2026 15:04
@alexejk
alexejk force-pushed the encoder-hardening branch from d208e34 to 89f1330 Compare August 31, 2026 15:16
@alexejk
alexejk force-pushed the encoder-hardening branch 2 times, most recently from 84e360b to 75f8a72 Compare August 31, 2026 15:36
All encoder output now goes through a small xmlWriter that latches the first
write error and escapes character data. This closes two gaps:

* Method names, struct member names (including xmlrpc tags) and map keys were
  written raw, so any of them containing & or < produced malformed XML.
* Most writes discarded their error, so a failing writer could yield a nil
  error from Encode with a truncated request already sent.

Values controlled by the package use raw(), anything supplied by the caller
goes through element()/text() and is escaped.
Doubles were formatted with %f, which pads to six decimal places and silently
loses everything beyond it: 0.1234567890123 went out as 0.123457, and both
1e-10 and 1e-300 became 0.000000. Values now use the shortest decimal
representation that round-trips exactly and satisfies the specification.

The specification allows only decimal point notation - "a plus or a minus,
followed by any number of numeric characters, followed by a period and any
number of numeric characters" - so exponent notation is avoided and a period
is always present, including for whole numbers.

NaN and infinities have no representation per the same section of the
specification, and previously went on the wire as NaN/+Inf/-Inf, which no
receiver can read as a number. They are now rejected with an error.
@alexejk
alexejk force-pushed the encoder-hardening branch from 75f8a72 to a632f79 Compare August 31, 2026 16:01
@sonarqubecloud

Copy link
Copy Markdown

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.

1 participant