Live data from Hacker News

Let's Destroy C

gist.github.com

71–80 of 192 posts

Re: Let's Destroy C

#71
post #70
post #55

Earlier quoted context omitted.

That'll be depending on undefined behaviour, though, correct?

That's not UB, that's implementation dependent, AFAIK the C standard says nothing about read-only memory. Attempting to modify a string literal is indeed UB but that would only happen if an attacker managed to attempt to modify the string, not when the program is used normally.

> That's not UB, that's implementation dependent, AFAIK the C standard says nothing about read-only memory.

If we're being pedantic, it's _unspecified behaviour_. The implementation isn't required to document how it would behave.

Re: Let's Destroy C

#72
post #57
post #54

Earlier quoted context omitted.

Can you please exemplify how you exploit a printf("Hello, World!\n") ?

That's a format string attack [0]. By modifying the start of that string, you can begin reading and writing to various parts of the stack. Whilst implementations may inline that string into a RO memory region - that's not defined behaviour, so you shouldn't depend on it. [0] https://owasp.org/www-community/attacks/Format_string_attack

> By modifying the start of that string

In order to modify that string, even in RW pages, the attacker already has to have access, at which point the point is moot. It's like saying "if you can change memory, then you can change memory"....

Re: Let's Destroy C

#73
post #63

Earlier quoted context omitted.

Good point. I suppose that you are talking about overwriting terminating NUL, do I get it right? puts() is vulnurable in exactly same way.

No, a format string attack. If you replace the start of the string with various specifiers, you can lift out pointer addresses and write to them. You can't do that with puts. Worst you can do with puts is read.

OK, understood. So what you meant was more like

   puts()'s attack surface is smaller than printf()'s.
This is not how your message appeared to me - "printf() is vulnerable to injections, use puts() instead". Both are vulnerable to "unintended read()-s".

Re: Let's Destroy C

#74

Ah, finally a modern successor to Bournegol: http://oldhome.schmorp.de/marc/bournegol.html

I know it's bad preprocessor magic, but I kinda liked that. I thought about hacking together a quick "Oberon-ish" to JS "transpiler" for a while, of course going along with a decidedly Wirth-ian code style. I might call it "werenotwirthy".

But there's also the appeal of the dreaded Incunabulum...

Re: Let's Destroy C

#75
post #63

Earlier quoted context omitted.

No, a format string attack. If you replace the start of the string with various specifiers, you can lift out pointer addresses and write to them. You can't do that with puts. Worst you can do with puts is read.

OK, understood. So what you meant was more like puts()'s attack surface is smaller than printf()'s. This is not how your message appeared to me - "printf() is vulnerable to injections, use puts() instead". Both are vulnerable to "unintended read()-s".

Not really.

printf is vulnerable to both read and _write_ attacks when you misuse it by only supplying the single argument. It's vulnerable to injections that can lead to remote execution and all sorts of CVEs.

puts is sometimes vulnerable to read attacks, but not often.

Re: Let's Destroy C

#76
Didn't one version of the "Ten Commandments of C" have a rule stating "Thou shalt not use the preprocessor to turn C into a different language"? :P

Re: Let's Destroy C

#77
post #25

Earlier quoted context omitted.

GNU doesn't really have lambdas. This is an abuse of the compound statement macro. IIRC compound statements, like I've presented, don't use trampolines. Nested functions definitely do, but that isn't quite what we're doing here. GCC _should_ compile using descriptors for the compound statements that lambda is expanding to instead of using trampolines. gcc -fno-trampolines -I. examples/lambda.c Works. There's no tramp…

#define lambda(ret_type, _body) ({ ret_type _ _body _; }) I found this one really fascinating, they're using both statement expression and nested functions. Their (reformatted) example of: int (*max)(int, int) = lambda(int, (int x, int y) { return x > y ? x : y; }); macro-expands to int (*max)(int, int) = ({ int _(int x, int y) { return x > y ? x : y;}; }); So they have a statement-expression with just one statement…

It's slightly different.

    { ret_type _ _body _; }
Notice the second underscore at the end? The compound statement contains a nested function definition followed by an expression statement which "returns" the function just defined. The function definition alone wouldn't work.

Re: Let's Destroy C

#78
post #10

GNU lambdas are incredibly evil. In order for lambdas to capture their environment and yet still be available as a function pointer, the compiler makes the stack executable and stores the trampoline code on the stack. C++ lambdas don't suffer from this problem.

clang blocks https://en.wikipedia.org/wiki/Blocks_(C_language_extension) also don't suffer from this problem :D

Re: Let's Destroy C

#79
lets go even further down the simplification way- and turn to lua..

  function xy (arg)
  end
looks like this

  xy z 
- so you are one typo away from a function call to nil & narnia without ever hearing about it.. life on the bleeding edge of sketch..

Re: Let's Destroy C

#80
post #44

I guess this article is to be taken lightly as kind of a "joke" ? The first proposed macro displayln is the archetype of malpractice. What if I want to do: if(some_condition) displayln("enjoy debugging that"); etc etc... almost all proposed changes seem to be awful ?

I guess that's one of the reason of the do { /.../ } while(false) pattern in macros.
Post reply on HN