Live data from Hacker News

Love C, hate C: Web framework memory problems

alew.is

111–120 of 218 posts

Re: Love C, hate C: Web framework memory problems

#111

Earlier quoted context omitted.

> Good C code will try to avoid allocations as much as possible in the first place. I've upvoted you, but I'm not so sure I agree though. Sure, each allocation imposes a new obligation to track that allocation, but on the downside, passing around already-allocated blocks imposes a new burden for each call to ensure that the callees have the correct permissions (modify it, reallocate it, free it, etc). If you're doing…

The most important pattern to learn in C is to allocate a giant arena upfront and reuse it over and over in a loop. Ideally, there is only one allocation and deallocation in the entire program. As with all things multi-threaded, this becomes trickier. Luckily, web servers are embarrassingly parallel, so you can just have an arena for each worker thread. Unluckily, web servers do a large amount of string processing, s…

> Ideally, there is only one allocation and deallocation in the entire program.

Doesn't this techically happen with most of the modern allocators? They do a lot of work to avoid having to request new memory from the kernel as much as possible.

Re: Love C, hate C: Web framework memory problems

#112

Good C code will try to avoid allocations as much as possible in the first place. You absolutely don’t need to copy strings around when handling a request. You can read data from the socket in a fixed-size buffer, do all the processing in-place, and then process the next chunk in-place too. You get predictable performance and the thing will work like precise clockwork. Reading the entire thing just to copy the body o…

This shared memory and pointer shuffling is of course fraught with requiring correct logic to avoid memory safety bugs. Good C code doesn't get you pwned, I'd argue.

Re: Love C, hate C: Web framework memory problems

#113

Earlier quoted context omitted.

The most important pattern to learn in C is to allocate a giant arena upfront and reuse it over and over in a loop. Ideally, there is only one allocation and deallocation in the entire program. As with all things multi-threaded, this becomes trickier. Luckily, web servers are embarrassingly parallel, so you can just have an arena for each worker thread. Unluckily, web servers do a large amount of string processing, s…

Arenas are a nice tool, but they don't work for all use cases. In the limit you're reimplementing malloc on top of your big chunk of memory.

The normal practical version of this advice that isn't a "guy who just read about arenas post" is that you generally kick allocations outward; the caller allocates.

Re: Love C, hate C: Web framework memory problems

#114

Good C code will try to avoid allocations as much as possible in the first place. You absolutely don’t need to copy strings around when handling a request. You can read data from the socket in a fixed-size buffer, do all the processing in-place, and then process the next chunk in-place too. You get predictable performance and the thing will work like precise clockwork. Reading the entire thing just to copy the body o…

This shared memory and pointer shuffling is of course fraught with requiring correct logic to avoid memory safety bugs. Good C code doesn't get you pwned, I'd argue.

> Good C code doesn't get you pwned, I'd argue.

This is not a serious argument because you don't really define good C code and how easy or practical it is to do. The sentence works for every language. "Good code doesn't get you pwned"

But the question is whether "Average" or "Normal" C code gets you pwned? And the answer is yes, as told in the article.

Re: Love C, hate C: Web framework memory problems

#115
I definitely don't love C that does atoi on a Content-Length value that came from the network and passes that to malloc.

Even before we get to how a malicious would interact with malloc, there is this:

> The functions atof, atoi, atol, and atoll are not required to affect the value of the integer expression errno on an error. If the value of the result cannot be represented, the behavior is undefined. [ISO C N3220 draft]

That includes not only out-of-range values by garbage that cannot be converted to a number at all. atoi("foo") can behave in any manner whatsoever and return anything.

Those functions are okay to use on something that has been validated in a way that it cannot cause a problem. If you know you have a nonempty sequence of nothing but digits, possibly with a minus sign, and the number digits is small enough that the value will fit into int, you are okay.

> A malicious user can pass Content-Length of 4294967295

But why would they when it's fewer keystrokes to use -1, which will go to 4294967295 on a 32 bit malloc, while scaling to 18446744073709551615 on 64 bit?

Re: Love C, hate C: Web framework memory problems

#116

As an aside, it's amusing that it took 25 years for C coders to embrace the C99 named struct designator feature: HttpParser parser = { .isValid = true, .requestBuffer = strdup(request), .requestLength = strlen(request), .position = 0, }; All the kids are doing it now!

It's only Microsoft's fault to have not implemented it for decades in MSVC. They stayed at C89 forever.

Re: Love C, hate C: Web framework memory problems

#117

Earlier quoted context omitted.

> Good C code will try to avoid allocations as much as possible in the first place. I've upvoted you, but I'm not so sure I agree though. Sure, each allocation imposes a new obligation to track that allocation, but on the downside, passing around already-allocated blocks imposes a new burden for each call to ensure that the callees have the correct permissions (modify it, reallocate it, free it, etc). If you're doing…

The most important pattern to learn in C is to allocate a giant arena upfront and reuse it over and over in a loop. Ideally, there is only one allocation and deallocation in the entire program. As with all things multi-threaded, this becomes trickier. Luckily, web servers are embarrassingly parallel, so you can just have an arena for each worker thread. Unluckily, web servers do a large amount of string processing, s…

I agree, which is why I wrote an arena allocator library I use (somewhere on github, probably public and free).

Re: Love C, hate C: Web framework memory problems

#118

Earlier quoted context omitted.

The most important pattern to learn in C is to allocate a giant arena upfront and reuse it over and over in a loop. Ideally, there is only one allocation and deallocation in the entire program. As with all things multi-threaded, this becomes trickier. Luckily, web servers are embarrassingly parallel, so you can just have an arena for each worker thread. Unluckily, web servers do a large amount of string processing, s…

Arenas are a nice tool, but they don't work for all use cases. In the limit you're reimplementing malloc on top of your big chunk of memory.

They don't work for all use-cases, but they most certainly work for this use-case (HTTP server).

Re: Love C, hate C: Web framework memory problems

#119

While the classic "Parse, don’t validate"[0] paper uses Haskell instead of C as its illustrative programming language, the approach detailed is very much applicable in these scenarios. 0 - https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va...

> While the classic "Parse, don’t validate"[0] paper uses Haskell instead of C as its illustrative programming language, the approach detailed is very much applicable in these scenarios.

Good thing someone (i.e. me) took the time to demonstrate PdV in C: https://www.lelanthran.com/chap13/content.html

Re: Love C, hate C: Web framework memory problems

#120

Earlier quoted context omitted.

The most important pattern to learn in C is to allocate a giant arena upfront and reuse it over and over in a loop. Ideally, there is only one allocation and deallocation in the entire program. As with all things multi-threaded, this becomes trickier. Luckily, web servers are embarrassingly parallel, so you can just have an arena for each worker thread. Unluckily, web servers do a large amount of string processing, s…

> Ideally, there is only one allocation and deallocation in the entire program. Doesn't this techically happen with most of the modern allocators? They do a lot of work to avoid having to request new memory from the kernel as much as possible.

last time i checked, the glibc allocator doesnt ask the OS that often for new heap memory.

Like, every ~thousand malloc calls invoked (s)brk and that was it.

Post reply on HN