Frontend
The same one-line table-parsing bug turned up in five separate tools. I fixed it four times.
Mahiro Hirakawa DEV Community
5 views
A lot of this project's specification lives in markdown tables, and several tools read them. Parsing a table row looks like a solved problem:
const cells = line.split('|').slice(1, -1).map((s) => s.trim());
That line is in more places than anyone had counted.
Two cells broke it
One spec table has a cell containing a set definition and another containing the length notation for a sequence. Written out, they carry a vertical bar inside the cell:
| E0 | the admitted set | N_t := {x \| E(x,t) = true} |
| S0 | length | \|·\| over a byte sequence |
Both are correct markdown. The bar is escaped, which is exactly what the format asks for. The naive split does not care that it was escaped, so both rows fractured into the wrong number of cells.
The symptom was not "the parser is broken"
This is the part I want to keep. What the run reported was:
verified_lying: 2
premise_defs: 2
Two definitions in the specification appeared to rest on nothing. That is a genuinely alarming finding, several steps more serious than a lost cell, and it is what everyone reacted to. The first stretch of work went into the two definitions themselves, both of which turned out to be fully reproduced by a proof and a test.
A parser failure arrives dressed as a content failure. The cells shifted, so a column that should have held a reproduction pointer held something else, and every check downstream honestly reported what it was given.
what the log said
what it meant
two definitions unverified
a column moved by one
the specification has a hole
the reader has a hole
It was the fourth time, and then the fifth
The same class had already been found in a proof-declaration printer and in the map generator. Each time, the person who hit it fixed the tool in front of them and carried on, which is a completely reasonable thing to do and is why it kept happening.
A fifth instance turned up in a shared cell-splitting helper the same week.
Nothing anywhere knew how many table readers existed. There was no wrong decision to point at. There was an absent list.
The repair was the inventory
The fix that ended it was not a better regex. Every tool that parses a table became a declared row, and a check reads that list:
OK_TABLE_READERS readers=7/7 escaped_pipe=1 lookalike=1
A new tool that reads tables has to be added to the list, and each one is exercised against a fixture containing both hazards. Adding the row is not optional in the sense that the check counts the readers it can find in the tree and compares them to the declared ones.
The second hazard is the one worth stealing. The mathematical notation does not actually want U+007C. It wants U+2223, the DIVIDES character, which looks nearly identical in a monospace font and is a completely different codepoint. A reader that learned about the escaped pipe and nothing else still gets that row wrong, silently, and the fixture now contains one of each.
Two things I keep
A bug found more than twice is not a bug. It is a missing inventory. The third occurrence is the signal to stop patching and start asking how many places have this shape, because the patch rate is clearly not keeping up with the discovery rate.
Expect a parser failure to present as a content failure. Whatever sits downstream of the parse will report faithfully on the garbage it received, and its report will be about your data rather than about your reader. When a check suddenly claims something alarming about content that was fine yesterday, suspect the thing that fed it before you suspect the content.
Read original: https://dev.to/mahirhir/the-same-one-line-table-parsing-bug-turned-up-in-five-separate-tools-i-fixed-it-four-times-4l5o
← Previous
What "Fully Automated" Actually Costs
Next →
Two friends pressed "Play" at the same time and both got a bot: lessons from building a browser 1v1 game
Related
How to Price Web Design Projects: A Practical Guide for Freelancers
Frontend
3
Dev.to (EN Zone)
Post Apache Ossie, what distinguishes semantic layers?
Frontend
5
Dev.to (EN Zone)
When should a QWidget animation stop its timer?
Frontend
2
Dev.to (EN Zone)
AI UI Design Without the Slop: Four Directions and a Choice
Frontend
9
DEV Community
Comments0
No comments yet — be the first