News for hackers. Stuff that matters.
Re:Parsing can become accidentally quadratic because of sscanf by PaulHoule on Monday March 01, 2021 @10:49AM (#26303916)
Another example of so many things wrong with the status quo.

(1) Naive people find liberation in text-based protocols that don't require tools to understand.

(2) With experience one finds that variable-length data structures are much more treacherous than fixed-length data structures: you find simplicity instead in binary data formats that are dead easy to parse.

(3) Floating point numbers are astonishingly expensive to parse and unparse to ASCII compared to how many FLOPs you could do in that time. All that, for a function that isn't quite correct... That is, the number 1/5, which you write as "0.2" doesn't actually exist in IEEE floats. You don't notice at first because that number unparses as "0.2" -- but then note that "0.1 + 0.2 == 0.3" is false in most computer languages.

(4) Null-terminated strings are the definition of insanity, rivaled only by "pointers are integers, integers are pointers"

One pet project of mine lately is a "Data Assembler" that takes a graph of data structures (say test data for a family of logic chips, graphics data for a laser light show, or "maps" to upload to the engine control unit in your car) in Python and converts it to a byte array that is incorporated into an Arduino program.

The total size of the structure could be up to 32kbytes on a small device, or up to 250kbytes or so on a big device, but the program memory is huge compared to the RAM which might be as little as 2kb so the unpacking code is going to stream the data with a small working area.

The minimum it has to do is put together blocks of data that have references to one another that are only resolved once all of the blocks are otherwise complete.

I deliberated a lot about how to handle variable length data structures and decided to embed a two-byte length before the block for all blocks. I could have saved some bytes when the length of the structure was known, but then I'd have to figure out how to code lengths then (e.g. for an array of 2-byte ints do I count the ints or bytes) and figured I'd make up my mind once.

Re:Parsing can become accidentally quadratic because of sscanf by CivBase on Monday March 01, 2021 @11:19AM (#26304288)
> Naive people find liberation in text-based protocols that don't require tools to understand.

I don't think text is necessarily the problem here. Other protocols might allow you to use less memory, but they aren't running into a memory limitation in this instance.

You can divide parsers into two groups: parsers designed to read data which follows a specific schema and parsers designed to read arbitrary data.

Schema-aware parsers have additional context which allows them to process the data much more efficiently. The stricter the schema, the more efficient the parser can be. Meanwhile, parsers for arbitrary data have no such context and must rely completely on syntax to parse the data. A poorly optimized schema-aware parser may still outperform a well optimized parser for arbitrary data.

You can still encode data as text and even use popular syntaxes like JSON or YAML with schema-aware parsers. I've personally helped design a schema-aware parser for XML data. But you should keep in mind that most third-party parsers for those syntaxes will be designed to parse arbitrary data. Parsers for arbitrary data can still be very fast - fast enough for many purposes. However, schema-aware parsers have a significant advantage when it comes to computational performance.

Re:Parsing can become accidentally quadratic because of sscanf by minitech on Monday March 01, 2021 @04:17PM (#26308531)
Text is the problem, here and everywhere else. Text encourages looking for delimiters, escaping, and flexibility (optional whitespace, case insensitivity, leading zeros, redundant signs, newline style compatibility). Compared to binary with length prefixes, that’s really slow, prone to injection vulnerabilities and subtle incompatibility, requires copying, introduces more side channels (the length of your message now depends on the values of numbers inside it!), ….
Re:Parsing can become accidentally quadratic because of sscanf by CivBase on Tuesday March 02, 2021 @09:55AM (#26315922)
Text =/= Variable Length

I can store fixed-length data using text. A strict schema can specify things like fixed lengths, value padding, orders for maps, exact whitespace rules, etc which can entirely remove the need for delimiters. A schema could even require length prefixes, just like you might use for a non-text format.

These concepts do not necessitate abandoning text. If you need the data to be readable/writable by a human with minimal tooling, you can still leverage text without sacrificing much parsing efficiency.

Re:Parsing can become accidentally quadratic because of sscanf by minitech on Tuesday March 02, 2021 @03:49PM (#26320457)
In theory, sure. In practice, nobody does, and length prefixes stop a format like that from being conveniently writable with a plain text editor.
Re:Parsing can become accidentally quadratic because of sscanf by CivBase on Tuesday March 02, 2021 @07:19PM (#26323125)
I work on avionics and we definitely use fixed-length text all the time. Text is often much more convenient than blobs, even when adhering to strict schemas.

Syntaxes like XML, JSON, YAML, etc have become popular for their convenience and versatility, but they do not represent the whole of what is possible with text.

Re:Parsing can become accidentally quadratic because of sscanf by renox on Thursday March 04, 2021 @08:50AM (#26342346)
You've not used enough Ada: its variable length string is so clunky that fixed sized text is used instead..
Re:Parsing can become accidentally quadratic because of sscanf by deathanatos on Monday March 01, 2021 @11:20PM (#26311874)
And once you get down to it, text still requires tools to parse. I routinely run stuff through `jq`, because despite JSON being a text format, actually consuming it as a human requires a tool. (Often to filter it, but sometimes just to colorize the output to make it legible.)
Re:Parsing can become accidentally quadratic because of sscanf by c-cube on Monday March 01, 2021 @07:07PM (#26310266)
That's orthogonal. Msgpack is basically json but easier to parse from C, and less inefficient on floats and integers.
Re:Parsing can become accidentally quadratic because of sscanf by nitrogen on Monday March 01, 2021 @11:06AM (#26304132)
Naive people find liberation in text-based protocols that don't require tools to understand.

As a huge fan of text-based protocols (but not of JSON or YAML), calling a whole class of debuggability, interoperability, and onboarding benefits "naive" is a bit much.

Re:Parsing can become accidentally quadratic because of sscanf by PaulHoule on Monday March 01, 2021 @11:31AM (#26304467)
It's a lot of the reason why software has gotten to be so porous in terms of security flaws.

I would trust programmers at Intel to handle FORTRAN-style data structures, and maybe even make a compiler in C.

I wouldn't trust anybody from Intel to write a web server or even a web application with PHP in that wild west of applications programming with strings they are sure to mess it up and thus leave a vulnerability in the management engine on your CPU. It might superficially look like good code, but American Fuzzy Lop will find the branch that isn't obvious, and so will some kid.

Re:Parsing can become accidentally quadratic because of sscanf by nicoburns on Monday March 01, 2021 @01:45PM (#26306459)
To me the problem seems to be old-school C programmers thinking that they don't need to use a library to parse a standard format. I have only ever seen JSON parsing errors in C and C++ codebases because they are the only languages where developers seem to think it's a good idea to parse JSON using string functions rather than a JSON parser.
Re:Parsing can become accidentally quadratic because of sscanf by PaulHoule on Monday March 01, 2021 @02:19PM (#26306955)
Some of that is that they don't have systems like maven or npm that would make it really easy to incorporate libraries into the build.

That said, what I like about C is that it is a simple language where you can throw out the standard library and start anew: it makes me think of the old versions of ALGOL that didn't specify mechanisms for I/O, and now we know you can specify that behavior in libraries and leave the language pure.

Re:Parsing can become accidentally quadratic because of sscanf by nicoburns on Monday March 01, 2021 @02:31PM (#26307131)
> Some of that is that they don't have systems like maven or npm that would make it really easy to incorporate libraries into the build.

Definitely! I wish the C and C++ communities would take this problem seriously.

> That said, what I like about C is that it is a simple language where you can throw out the standard library and start anew

This definitely is a nice property. But it's not just C that can do this. You can for example do this with Rust, and get an excellent package management system (that can indeed package these alternatives to the stdlib) to boot.

Re:Parsing can become accidentally quadratic because of sscanf by Cloudef on Monday March 01, 2021 @02:43PM (#26307348)
As a C programmer, i can say that most of the json libraries fail on simple fuzzing test, or do some other idiotic stuff like trying to handle numbers (and doing it wrong of course). We have awesome parser generators such as ragel, yet people still handroll parsing code that is both buggy and slow.
Re:Parsing can become accidentally quadratic because of sscanf by nicoburns on Monday March 01, 2021 @05:56PM (#26309639)
> We have awesome parser generators such as ragel, yet people still handroll parsing code that is both buggy and slow.

Wasn't ragel responsible for the cloudbleed vulnerability? Wherever possible we really shouldn't be using C at all.

Re:Parsing can become accidentally quadratic because of sscanf by Cloudef on Tuesday March 02, 2021 @01:02AM (#26312322)
No, the bug was in code that was feeding input to ragel [1]. Ragel itself was fine. (Ragel also can output to non C languages). I've used ragel myself extensively and it's really rock solid, I've fuzzed the state machines it generates a lot. I've even used it to parse protobuf specifications and generate code from them, the company still uses that code. (and it's really not a lot of code)

1: https://blog.cloudflare.com/incident-report-on-memory-leak-c... (As for cloudflare, I don't think it's good idea to let single company to MITM the whole internet)

Re:Parsing can become accidentally quadratic because of sscanf by nicoburns on Tuesday March 02, 2021 @05:33AM (#26313830)
It sounds like Ragel still requires the user to "use it correctly", which is really not great.
Re:Parsing can become accidentally quadratic because of sscanf by Cloudef on Tuesday March 02, 2021 @10:13AM (#26316103)
That's like saying driving car into a wall full speed should not kill you
Re:Parsing can become accidentally quadratic because of sscanf by nicoburns on Tuesday March 02, 2021 @11:20AM (#26316926)
It's like saying that we ideally shouldn't have cars that can drive full speed into a wall, or at least that these cars shouldn't be the cars that most people use. And indeed modern cars will generally at least attempt to break before they hit a wall. It seems not too fanciful to think that in another 10 years we will have cars that can reliably prevent themselves from being driven into walls.

Our tech with regard to type and memory safety is more advanced than our car tech: we already have the tech to prevent these errors. And I believe we should be using it wherever possible. Obviously there will be exceptions (the more obvious being legacy codebases), but they should be exceptions.

Re:Parsing can become accidentally quadratic because of sscanf by YuriNiyazov on Tuesday March 02, 2021 @12:01PM (#26317437)
My Subaru will do its best to turn off the gas and auto break when it detects I’m about to drive into a wall.
Re:Parsing can become accidentally quadratic because of sscanf by perl4ever on Monday March 01, 2021 @07:50PM (#26310559)
I used to be the only one where I worked who would use the standard library for xml in perl rather than just ad hoc regexes.

They'd recycle my scripts when dealing with very large files but wouldn't learn it themselves.

Re:Parsing can become accidentally quadratic because of sscanf by pjc50 on Monday March 01, 2021 @10:56AM (#26303989)
> variable-length data structures are much more treacherous than fixed-length data structures

A fixed-length structure is only fixed until you need to add a field to it. I understand the appeal, but good solutions seem to be very rare here. ASN.1 was possibly the first attempt but turned into a total nightmare. Protobuf seems to be doing a reasonable job, but only as a wire format and not a persistence format.

Text always "works", even if inadequately. And it can be handled with your normal diff and editing tools.

Re:Parsing can become accidentally quadratic because of sscanf by astrobe_ on Monday March 01, 2021 @01:29PM (#26306183)
> Text always work

Windows vs Linux end-of-line markers often screws-up things. UTF often screws-up things. Tab-vs-space sometimes screws-up things. Text is related to Postel's principle, which is often questioned because it leads to sloppy implementations on one side and complex implementations on the other side, and other bug-is-now-a-feature niceties.

I designed a couple of small internal protocols, and have been maintaining them for at least a decade. Maintenance time is nearly 0 because I never had to add a field to them. Even though the software using them evolved a lot and in unexpected ways.

Yes, they stood the test of time because they solved the problem we had, and those problems didn't evolve much. Not every protocol or format needs to be hyper-extendable and scalable.

> even if inadequately

So it works poorly but it works, so it can be shipped. That's why you buy a new smartphone every two year and don't see much improvement in response time or battery life.

Re:Parsing can become accidentally quadratic because of sscanf by gpm on Monday March 01, 2021 @11:02AM (#26304063)
We've been using protobuf as a persistence format without issue?
Re:Parsing can become accidentally quadratic because of sscanf by nitrogen on Monday March 01, 2021 @11:08AM (#26304159)
A self-describing format like MessagePack can be easier to build readers for in other applications, or if the schema is lost or changed.
Re:Parsing can become accidentally quadratic because of sscanf by gpm on Monday March 01, 2021 @11:52AM (#26304794)
If we've lost access to the schema, then we've lost access to our entire source repository, so we probably don't need to read our data anymore?

I guess I could see that being an interesting property in software that wants to deal with incompatible forks, or software that for whatever reason wants other people to read their data but is unwilling to ship a schema with it, but just for persistence on backend servers it doesn't seem like a very interesting property or worth the extra space requirements.

Re:Parsing can become accidentally quadratic because of sscanf by imtringued on Tuesday March 02, 2021 @06:38AM (#26314202)
CBOR is the gold standard for schema free data.
Re:Parsing can become accidentally quadratic because of sscanf by pjc50 on Monday March 01, 2021 @03:59PM (#26308327)
You have. Far more apps out there are using JSON or XML, including (as we've seen GTA).
Re:Parsing can become accidentally quadratic because of sscanf by gpm on Monday March 01, 2021 @07:07PM (#26310269)
Ah, you were just talking about popularity not fitness? Fair enough.
Re:Parsing can become accidentally quadratic because of sscanf by adrian_b on Monday March 01, 2021 @12:02PM (#26304958)
Whenever floating-point numbers converted to text are not intended to be used by a human, converting the numbers to decimal is a great mistake in my opinion.

The floating-point numbers should be converted to text as hexadecimal, e.g., in C99 and later, using printf with the %a or %A conversion specifiers.

Even when a human uses the textual floating-point numbers, if they are used only for making copies or comparisons, the hexadecimal numbers are more convenient and they are free of conversion errors.

Re:Parsing can become accidentally quadratic because of sscanf by orf on Monday March 01, 2021 @02:27PM (#26307080)
How would the compiler be able to use any fast, floating point specific instructions if you parsed it as a hexadecimal string?
Re:Parsing can become accidentally quadratic because of sscanf by MauranKilom on Monday March 01, 2021 @03:33PM (#26308012)
Not sure I understand the question. The suggestion is to use hexfloats, as they are unambiguous and straightforward to convert from and to (as opposed to anything with decimal significands): https://www.cplusplus.com/reference/ios/hexfloat/
Re:Parsing can become accidentally quadratic because of sscanf by firebacon on Monday March 01, 2021 @03:43PM (#26308124)
You don't need any specific instructions. The hex encoded double contains the final binary representation of the floating point number. So no conversion is required to load it, except maybe for swapping around bytes on some architectures. Conceptually:

    double v;
    memcpy(&v, "\x00\x00\x00\x00\x00\xe4\x94\x40", sizeof(v)); // LE
Re:Parsing can become accidentally quadratic because of sscanf by astrobe_ on Monday March 01, 2021 @12:45PM (#26305599)
On (2): implicit type promotions with unsigned and signed types can make it no-so-easy in C. FWIW, I always test with bytes with the sign bit on (on two's complement architectures, never worked with others) when I do stuff like that.

On (3): never perform equality tests on FP numbers in languages that use IEEE standard FP format.

On (4): I have worked both with ASCIIZ and counted strings, I think both have their pros and cons. But if you are writing stuff that has any contact with C/C++, it's often a bad idea to go against the stream. No, auto-adding a final 0 to your counted strings won't save the day every time.

Re:Parsing can become accidentally quadratic because of sscanf by a1369209993 on Monday March 01, 2021 @02:14PM (#26306872)
Never perform equality tests on FP numbers period - it defeats the purpose of using floating point. This is not specific to the IEEE format.
Re:Parsing can become accidentally quadratic because of sscanf by imtringued on Tuesday March 02, 2021 @06:43AM (#26314245)
Tell that to lua and javascript developers who only have access to FP numbers.
Re:Parsing can become accidentally quadratic because of sscanf by a1369209993 on Tuesday March 02, 2021 @02:40PM (#26319529)
shrug They also only have access to IEEE FP numbers, so that applies equally much to the parent.
Re:Parsing can become accidentally quadratic because of sscanf by astrobe_ on Tuesday March 02, 2021 @03:32PM (#26320230)
If my memory serves, IEEE FP is accurate for those real numbers that are also integers (at least on some range). JS users are safe as long as they stay within the integer algebra (ie they don't use division, mainly, or perhaps round up the result). Lua users have the extra option to recompile their interpreter it uses integers.
Re:Parsing can become accidentally quadratic because of sscanf by a1369209993 on Tuesday March 02, 2021 @06:40PM (#26322781)
That's fair as far as it goes (I pedantically should have said general-purpose FP numbers), but, again, applies equally well (actually more so, since they were talking about IEEE FP specifically) to the parent post.
Re:Parsing can become accidentally quadratic because of sscanf by nly on Monday March 01, 2021 @11:22AM (#26304321)
I agree generally that if you can afford the cycles to serialize and deserialize from decimal ASCII ("0.2") that you can probably afford to use a decimal numeric type in your business logic.

Personally I blame the C standard for not splitting strtod in to 1 parsing function (returning an integer and the power of ten), and 1 computation/conversion function. Without this you're basically hosed with respect to locales.

Re:Parsing can become accidentally quadratic because of sscanf by arbitrage on Monday March 01, 2021 @02:41PM (#26307321)
> Null-terminated strings

There is nothing inherently wrong about a null-terminated string convention.

Re:Parsing can become accidentally quadratic because of sscanf by PaulHoule on Monday March 01, 2021 @02:43PM (#26307353)
There's no guarantee that it terminates.
Re:Parsing can become accidentally quadratic because of sscanf by acmj on Monday March 01, 2021 @07:24PM (#26310392)
I am not sure there is a universally better solution. If a function takes both string and its length (e.g. strncmp), there is no guarantee that the length is correct. Or like C++, you always represent a string by a (len,max,ptr) 3-tuple, but 1) this is not a primitive type and 2) len and max waste memory when you have millions of short strings.
Re:Parsing can become accidentally quadratic because of sscanf by PaulHoule on Tuesday March 02, 2021 @08:38AM (#26315152)
If it is that bad use a variable length length code like the utf-8 transformation. For strings smaller than 127 bytes overhead is the same as NUL.
Re:Parsing can become accidentally quadratic because of sscanf by acmj on Tuesday March 02, 2021 @06:09PM (#26322463)
This increases code complexity. Also, for many applications, we prefer to have a max field for dynamic strings. Each type of string representation has its own pros and cons. This comes back to my original comment: there is not a universally better solution.
Re:Parsing can become accidentally quadratic because of sscanf by api on Monday March 01, 2021 @11:08AM (#26304154)
I'll add that variable length stuff is inefficient to parse as it breaks instruction level parallelism. Later parsing events become dependent on earlier events.
Re:Parsing can become accidentally quadratic because of sscanf by fokinsean on Monday March 01, 2021 @12:20PM (#26305242)
> (4) Null-terminated strings are the definition of insanity

Could you elaborate on this one? I've only used C in college and don't know why this is bad.

Re:Parsing can become accidentally quadratic because of sscanf by syrrim on Tuesday March 02, 2021 @12:20AM (#26312140)
I would point out two main issues:

1. Such a string cannot contain arbitrary bytes. Since it is frequently useful to work with arrays of arbitrary bytes, we have to repeat every library function twice, once for strings that can contain nuls (the mem* series of functions), and once for strings terminated by nuls (the str* series of functions). The latter are much better supported, and are easier to work with, so we frequently see programs that trip over strings with nuls in them for no particularly good reason.

2. We often want to modify strings, not just read them. Modifications often need more space than was in the original string. A nul terminated string cannot say how much room beyond the current length is allowed to be written to. By default, most library functions assume that there is enough space, however this is frequently an unsafe assumption. This again causes us to duplicate every library function twice over in order to specify the size of the buffer (the strn* series of functions). Since, again, these functions are poorly supported and harder to use, we see many many instances of programs that have buffer overflow bugs, and therefore likely RCEs, for no good reason at all.

Re:Parsing can become accidentally quadratic because of sscanf by ben509 on Monday March 01, 2021 @01:29PM (#26306182)
Besides the fact that you have to walk the string just to find the length of it...

Null-terminated strings try to save space by encoding the string length by convention. This can fail due to off-by-one errors, mistakenly allocating a fixed buffer, strings that have an unexpected null in them, and more.

Those can lead to all kinds of nasty problems like buffer overflows, which allow someone who can craft an input to write arbitrary stuff into memory.

God only knows how many security vulnerabilities and performance problems could be traced back to null terminated strings.

Re:Parsing can become accidentally quadratic because of sscanf by birktj on Monday March 01, 2021 @01:16PM (#26305981)
As is the case in this article it often happens that having the length of a string is required for certain operations, which leads to a lot of calls to strlen. This doesn't really seem like such a big problem to begin with as one assumes that the operations that require the length also have linear complexity. However it turns out (like in the article) that this is not always the case which leads to unexpected quadratic algorithms. The pointer + length representation is only 7 bytes longer on modern architectures and does not have this problem and has a few other advantages like being able to create substrings without allocating new memory.
Re:Parsing can become accidentally quadratic because of sscanf by wnoise on Monday March 01, 2021 @02:01PM (#26306681)
In fact, having the length of the string was not required. Certain ways of implementing scanf() required getting the length of the string, or otherwise scanning the whole thing.

But saner ways did not.

Re:Parsing can become accidentally quadratic because of sscanf by ativzzz on Monday March 01, 2021 @01:06PM (#26305867)
It's incredibly easy to do something wrong and cause bugs or security issues in your app.

Or, compare string manipulation in C with any high level language like Ruby, Python, JS and the ease of use is night and day.

Re:Parsing can become accidentally quadratic because of sscanf by edflsafoiewq on Monday March 01, 2021 @04:24PM (#26308618)
Another reason is a substring of a nul-terminated string is only nul-terminated if it is a suffix. So slicing out a substring generally requires copying to a new buffer so you can append the nul byte.
Re:Parsing can become accidentally quadratic because of sscanf by TwoBit on Monday March 01, 2021 @02:09PM (#26306804)
The decision to use 0-terminated strings in C may be the single worst decision in programming language history, at least from a security standpoint.
Re:Parsing can become accidentally quadratic because of sscanf by perl4ever on Monday March 01, 2021 @07:57PM (#26310608)
"in-band signaling is the root of all evil" -anonymous
Re:Parsing can become accidentally quadratic because of sscanf by rmrfrmrf on Monday March 01, 2021 @01:21PM (#26306053)
This whole rant is a bit of a non-sequitor for a minor performance bug with a working fix.