Live data from Hacker News

Parse, Don’t Validate – Some C Safety Tips

lelanthran.com

1–10 of 78 posts

Re: Parse, Don’t Validate – Some C Safety Tips

#2
The trouble I have with this approach (which, conceptually, I agree with) is that it's damned hard to do anything with the parse results. Want to print that email_t? Then you're right back to char*, unless you somehow write your own I/O system that knows about your opaque conventions.

So you say, okay, I'll make an `email_to_string` function. Does it return a copy or a reference? Who frees it? etc, etc, and you're back to square one again. The idea is to keep char* and friends at "the edge", but I've never found a way to really achieve that.

Could just be my limitations as a C programmer, in which case I'd be thrilled to learn better.

Re: Parse, Don’t Validate – Some C Safety Tips

#3
`_t` should not be used for custom types since it's reserved for future standard types (and/or types declared in a header you might include someday). This does cause real-world problems (`key_t` anyone?).

Gratuitous allocations are gratuitous.

The whole "prevent double free" claim is completely bogus. Setting a variable to `NULL` only works for cases where there is one, obvious, owner, which is not the circumstance under which double free is prone to happening in the first place. Actually preventing double free requires determining ownership of every object, and C sucks at that.

Re: Parse, Don’t Validate – Some C Safety Tips

#4
post #2

The trouble I have with this approach (which, conceptually, I agree with) is that it's damned hard to do anything with the parse results. Want to print that email_t? Then you're right back to char*, unless you somehow write your own I/O system that knows about your opaque conventions. So you say, okay, I'll make an `email_to_string` function. Does it return a copy or a reference? Who frees it? etc, etc, and you're ba…

email_t doesn't have to be opaque; if it's just a visible wrapper around char* then you can still do everything with it as a char* (that is, everything you do with strings).

The benefit is to avoid treating char*s as email_t, not avoiding treating email_t as char*.

Re: Parse, Don’t Validate – Some C Safety Tips

#5
post #4
post #2

The trouble I have with this approach (which, conceptually, I agree with) is that it's damned hard to do anything with the parse results. Want to print that email_t? Then you're right back to char*, unless you somehow write your own I/O system that knows about your opaque conventions. So you say, okay, I'll make an `email_to_string` function. Does it return a copy or a reference? Who frees it? etc, etc, and you're ba…

email_t doesn't have to be opaque; if it's just a visible wrapper around char* then you can still do everything with it as a char* (that is, everything you do with strings). The benefit is to avoid treating char*s as email_t, not avoiding treating email_t as char*.

In the example code they explicitly put the struct in the c file so the char* is not available.

If you're suggesting getting around this by casting an email_t* to char* then I wish you good luck on your adventures. There's some times you gotta do stuff like that but this ain't it.

Re: Parse, Don’t Validate – Some C Safety Tips

#6
post #4
post #2

The trouble I have with this approach (which, conceptually, I agree with) is that it's damned hard to do anything with the parse results. Want to print that email_t? Then you're right back to char*, unless you somehow write your own I/O system that knows about your opaque conventions. So you say, okay, I'll make an `email_to_string` function. Does it return a copy or a reference? Who frees it? etc, etc, and you're ba…

email_t doesn't have to be opaque; if it's just a visible wrapper around char* then you can still do everything with it as a char* (that is, everything you do with strings). The benefit is to avoid treating char*s as email_t, not avoiding treating email_t as char*.

(Using a thin wrapper like this to add safety is called the newtype pattern, if anyone wants to know.)

Re: Parse, Don’t Validate – Some C Safety Tips

#7
This stuck out:

  email_t theEmail = parseEmail(untrustedInput);
  if (theEmail == PARSE_ERROR) {
    return error;
  }
An email_t is not a parse error, and a parse error is not one of the emails, so this shouldn't compile (and I don't take 'pseudocode' as an excuse).

Re: Parse, Don’t Validate – Some C Safety Tips

#8
post #4

Earlier quoted context omitted.

email_t doesn't have to be opaque; if it's just a visible wrapper around char* then you can still do everything with it as a char* (that is, everything you do with strings). The benefit is to avoid treating char*s as email_t, not avoiding treating email_t as char*.

In the example code they explicitly put the struct in the c file so the char* is not available. If you're suggesting getting around this by casting an email_t* to char* then I wish you good luck on your adventures. There's some times you gotta do stuff like that but this ain't it.

You could probably get away with the typecast if you satisfy the "common struct prefix" requirement, that's nowhere near necessary.

While the article does hide the internal char*, that's not strictly necessary to get the benefit of "parse, don't validate". Hide implementation details sure, but not everything is an implementation detail.

Re: Parse, Don’t Validate – Some C Safety Tips

#9
post #7

This stuck out: email_t theEmail = parseEmail(untrustedInput); if (theEmail == PARSE_ERROR) { return error; } An email_t is not a parse error, and a parse error is not one of the emails, so this shouldn't compile (and I don't take 'pseudocode' as an excuse).

> and I don't take 'pseudocode' as an excuse

They write the non-pseudo variant later. There, the return value is a pointer and the check is against NULL. Which is fairly standard for C code, albeit not always desirable.

Re: Parse, Don’t Validate – Some C Safety Tips

#10
post #7

This stuck out: email_t theEmail = parseEmail(untrustedInput); if (theEmail == PARSE_ERROR) { return error; } An email_t is not a parse error, and a parse error is not one of the emails, so this shouldn't compile (and I don't take 'pseudocode' as an excuse).

> and I don't take 'pseudocode' as an excuse

Weird hill to die on, since neither email_t nor PARSE_ERROR were defined in the sample snippets. How do you know PARSE_ERROR is not email_t?

Post reply on HN