Hacker Newsnew | comments | show | ask | jobs | submit login
Printable True Bugs Wait Posters (natashenka.ca)
234 points by liotier 442 days ago | 156 comments



Pro tip: when you develop with gcc, don't settle for anything less than

    gcc -ansi -pedantic -Wall
At university I often had people coming to me and asking, "my program compiles correctly, but it keeps crashing / doing weird things; what did I do wrong?". I always said, "add '-ansi -pedantic -Wall' to the compile flags and come back to me when you cleared that wall of warnings down to nothing". Every single time the problem was directly or indirectly caused by the things that were in the warning messages.

It's a shame that the default choice of GCC flags make this compiler pretty much useless for work.

The warnings are there to help you. You can choose to ignore them and that's fine, as long as you do it deliberately and with a damn good reason, not because you don't even know they're there.

-----


You can go further and specify a particular standard, plus extra warnings not included in -Wall:

    gcc -std=c99 -Wall -Wextra -Werror
I'm not sure if -pedantic is still beneficial in that case. The gcc documentation had a list of every warning category, and which parameters enable each warning. This SO question was also interesting: http://stackoverflow.com/questions/11714827/how-to-turn-on-l...

-----


A tiny comparison: -Wall -pedantic gives me:

  warning: C++ style comments are not allowed in ISO C90
  warning: ISO C90 forbids mixed declarations and code
-Wall -Wextra gives me:

   warning: unused parameter ‘type’
For me, -Wextra is much more useful for finding messy code.

-----


Use both of them. The last warning is about messy code, but the first two will help you keep the code portable.

-----


-std=cNN specifies the base language standard. Much existing code depends on GCC extensions to that standard (for better or for worse), so it is often necessary to use -std=gnuNN instead (specifying base language dialect + extensions).

-----


clang has -Weverything, which means, well, warn about everything.

Also —analyze to run the static analyzer: http://clang-analyzer.llvm.org

-----


One of my professors in college wouldn't accept code that didn't compile with the invocation.

"Your compiler is trying to help you. Listen to it."

-----


Even when you do have a good reason to ignore them, you should still either disable that specific type of warning or, better yet, disable that specific warning for that specific spot in code using gcc's diagnostic pragmas [1].

[1] http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Diagnostic-Pragm...

-----


I agree. This way you signal to other programmers reading the code that you were in fact aware of the warning and made a conscious decision to disregard it.

-----


-ansi and -pedantic often produce a lot of useless output unless your goal is to really target C89.

-Wall is enough to catch most relevant things, throw in -Wextra if you want overkill, not -ansi -pedantic.

-----


> It's a shame that the default choice of GCC flags make this compiler pretty much useless for work.

I disagree (not "strongly" because your clarification in the next paragraph). That's only true if you don't know what are you doing.

That said, I am a big fan of gcc's -Wall since the late 90s, and I can tell you gcc has improved a lot since then.

-----


I think even the most skilled programmer can benefit from making their code pass -Wall completely, even if just for the sake of sharing with other developers (but we all make mistakes and it'll likely catch some of those too!).

-----


There's a reason that for quite a number of these warnings, Go has either designed the causes out of the language (no implicit casting, only manual conversions), or promoted them to compiler errors (unused variables and imports).

-----


Note: -ansi is equivalent to -std=c90 (in C mode). If you want C99 or C11 support, use -std=c99 or -std=c11.

-----


-ansi is one of the most poorly named compiler flags of all time; C11 is the current ANSI C standard, but compiling with -ansi in GCC specifies a language dialect that’s a quarter of a century old(!)

-----


It was named when "ANSI or not ANSI?" was the interesting question, and stuck around for compatibility. It should be kept and its semantics should not be changed, but it should be called out as deprecated. At least the gcc man page does say "In C mode, this is equivalent to -std=c90. In C++ mode, it is equivalent to -std=c++98."

-----


True, but colloquially, when people say "ansi C" they almost always mean C89.

-----


True, but when people say "ansi C", then Clinton is almost always president.

(I say this because these days, I hear "C89" or "C90", "C99", or "C11". People who say "ANSI" get asked for clarification.)

-----


That is a very developer mindset.

Remember, many more of us use the compiler to build packages in the wild, we need it to be fairly permissive to hope to get things to build.

-----


Yes, but if more developers used these flags the world would be a better place. Whenever I have the time, I build with these flags and report bugs back to the upstream developers. Then I drop the flags and move on with my life :)

-----


That is genius! This would be a great way to get university kids to contribute to the OSS movement.

-----


Furthermore, I wish I had known earlier how much I could contribute to the open-source community by simply downloading a product, walking through their documentation, and submitting corrections, and little usability improvements to both the interfaces and documentation. It's an easy way to start learning your way around the code and internal architecture.

-----


This seems to deserve mention here: https://openhatch.org

-----


It may be a developer mindset sure, but look at the post you are commenting on... It's a series of posters made for developers to influence their choice of memory handling functions. Context matters quite a bit.

-----


Ansi and pedantic are solely about standards compliance; that's often not what I want. It means my code might not be portable to other compilers, but a lot of other compilers implement much or all of GCC's extensions. If the extensions help you write better, safer code faster, use them! I whole-heartedly agree about -Wall, and would add -Werror and -Wextra, and would recommend skimming the list for other things that might be appropriate but aren't enabled by default.

-----


If you have clang available, the -fsanitize flag is also incredibly helpful for runtime analysis.

-----


Half the people in this thread seem to have missed the point. This article is not supporting 100% abstinence of these functions. It is doing exactly the opposite - and showing up people who say "never do this" or "that is always wrong" as being as ridiculous as those who blindly support abstinence from sex. This kind of tunnel vision, learning by rote, and refusal to teach what is really happening, is exactly the same stupid attitude that creates bad programmers, as it creates unbalanced teenagers.

Perhaps, just like condoms, memcpy, strcpy, strcat are dangerous or ineffective 10% of the time. But that other 90% of the time, when used correctly, they are perfectly safe, fun and essential to learning and growing. Avoiding them completely does not create a healthy relationship between a language and its programmer. I realize that not everyone in this thread is a C programmer, but this prevailing attitude of saying "this should never be done/used" just because you're heard that from someone else, is a really petty, annoying, and persistent aspect of programmer culture.

-----


Perhaps, but tested and true advertising methodology is 1) find a undeniable grain of truth, 2) wrap your message around it, so the consumer is confused into thinking your message is by association true too.

You might be right about the sarcastic message 'wrapping', but these posters only work because the messages they're wrapped around are true.

I certainly didn't come away from those posters going, 'dang, those guys... so over the top; there's nothing wrong with using strcpy, you're making a fuss about nothing'.

-----


I'm a beginner C programmer, maybe you can share your experience with me.

I've found bugs in libraries where sprintf was used instead of snprintf and it caused crashes. So I know from experience of cases where snprintf was a better choice than sprintf. And I've certainly coded a few off-by-one errors in my time so I can sure understand it's easy to get the destination buffer size wrong!

I'm not doing anything performance-critical with strings. Under what circumstances should I use sprintf instead of snprintf and what benefits will I see?

-----


If you understand the difference between snprintf and sprintf, what trouble it can cause, and where to use it, it sounds like you're already doing great. What would be bad was if you had the blind notion that "snprintf is good" and "sprintf is bad" without knowing why.

As for an example of when you might want to use sprintf. If you compile to C89 (ANSI) snprintf isn't included in the standard so you're left with sprintf if you want your code to be portable.

A better example is strcpy though. A function which is completely normal and safe when used correctly, but someone with the wrong idea might use strncpy as a "safer" version and cause themselves more trouble for not knowing what is going on. As if to prove my point you can see someone advocating this exact thing in another comment tree in this thread. They've probably heard from someone that the "n" version of functions are safe. If they'd actually looked into it they'd realize strncpy doesn't do what you might think.

-----


Maybe he's saying that migrating to the less safe, more performant functions can ... wait.

-----


Or even better, don't use C for string handling.

It's too much trouble for too little gain.

I think the areas where C is a good and effective solution are shrinking and safer languages are becoming more common and faster (even C++)

The C syntax, not its library doesn't allow for good string handling. String handling should be built deeper into the language, and, yes, even though it is possible to have safe C code, it's very hard. So try when it's worth it.

-----


Saying C is "very hard" is useful to dissuade the unprepared from writing buggy, vulnerable software, but for the experienced developer with modern tools, C is at worst "tedious". Some simple habits, like always writing your malloc() and free() calls at the same time in balanced pairs, can make C quite managable. Add valgrind, unit tests, and static analysis, and I'd have much more confidence in a good C program than an average program in a weakly typed language.

-----


For people not familiar with it, Valgrind will run your program in a VM and trace memory accesses. It detects when you read from unitialized/unallocated memory, don't free your memory, etc. Almost every time I have had a non-logic bug in C code, in had a corresponding warning in Valgrind.

-----


"malloc() and free() calls at the same time in balanced pairs"

There is no stable correspondence between number of malloc calls and number of free calls. I might allocate things in 10 places that get freed in one, or vice-versa. A simple example would be "parse a packet and send the built packet (through a message queue) to handling code."

-----


While it's true that there are times when you can't achieve it, I intend to suggest limiting oneself to design patterns that facilitate simpler memory management, and implementing both halves of the memory management equation at the same time.

Naturally there's a tradeoff; if redesigning your code to allow one malloc() to one free() would introduce more bugs in logic than it would solve in memory issues, then it's not worth it.

-----


I'm pretty sure the its very hard refers to string handling in C, and also fairly solid in my agreement that unless you have a very very good reason, that is one of the places most people are better off staying away from (especially once you start playing with C unicode constructs).

(but your point is totally valid with regard to C in general~)

-----


Is there a good string handling library for C?

-----


Other HNers have recommended bstring. I haven't tried it myself.

http://bstring.sourceforge.net/

-----


BString relies on undefined behavior for security:

  The reason is it is resiliant to length overflows is that
  bstring lengths are bounded above by INT_MAX, instead of
  ~(size_t)0.  So length addition overflows cause a wrap
  around of the integer value making them negative causing 
  balloc() to fail before an erroneous operation can occurr.
I wouldn't touch this library.

-----


Some simple habits, like always writing your malloc() and free() calls at the same time in balanced pairs, can make C quite managable.

One can also use the Boehm GC if they feel it necessary.

-----


I'm curious as to who uses a garbage collector in C. It seems like if you're using C, you probably are in a situation where you want as close control of that kind of stuff as possible (short of assembly).

-----


The same thing can be said about malloc. It's a matter of degree, and different projects have (sometimes subtly) different requirements.

-----


Expanding - in particular, Boehm seems to only run collections on allocations. If your code is structured such that you don't allocate during periods when you need more precise control (already a good idea, if you are using malloc!) then this won't have an impact.

-----


GCC and Mono use it internally, I believe.

It's a very conservative garbage collector at the end of the day. It can be tweaked so as to be completely bare bones, and the performance impact is very benign. Rather, memory consumption is its weakness.

-----


This is the point people often miss-understand when discussing different programming languages. Few languages prevent you doing anything. No one claims they do.

The point is some languages encourage you to do things correctly, others, make it an uphill struggle.

-----


> safer languages are becoming more common and faster

> though it is possible to have safe C code, it's very hard

A dull knife is pretty safe for most people. It's still possible to shove it into your eye and blind yourself, but other than those extreme cases it won't cause much injury when used in the regular manner. However, it is also extremely inefficient at the purpose it was designed for: cutting things.

There are, of course, safer alternatives to a knife. EMTs use special tools designed to fit a seatbelt or cloth into a small slot and slice through without any risk to a person; they also have specially designed shears which make it difficult to cut flesh, but easily cut through nylon and leather. Utility knives have retractable blades to reduce injury, and other tools are designed to fit specific materials into slots and make cutting people impossible.

All of those are purpose-driven and application-specific solutions, however. For the most high performance and general purpose application, a really sharp fixed-blade knife is still the most precise and efficient tool for the job. When wielded correctly it is still safe and efficient. But the practitioner is not protected from harming themselves; it's expected that they know what they're doing. And really, it's not that hard to learn how to use it correctly.

But I totally get that it's easier to use a dull knife or scissors than learn all about knives, and it gets the job done.

-----


"A dull knife is pretty safe for most people."

While your point is true, I want to object to your metaphor. I object for safety purposes. In fact, a dull knife is more dangerous than a sharp knife for most anyone who needs to cut things.

You need to press much harder with a dull knife and sometimes even to saw down into the object. You may even need to get a firmer grip on the object you're cutting to counter all that force. Those are very dangerous behaviors. A sharp knife that cuts easily is much, much safer.

-----


A dull knife is safer at rest. A sharp knife is safer in use.

-----


Not true. A dull knife is dull; it's not dangerous at all because it basically can't cut anything. A half-dull or half-sharp knife is dangerous. It can cut, but you don't know how much, and variations in the blade make it unpredictable, in addition to the behaviors you defined.

-----


I would describe a typical kitchen table knife as a "dull knife", and trying to use that for tasks to which it is not suited can certainly lead to injury.

-----


" And really, it's not that hard to learn how to use it correctly."

Patronizing and 100% wrong.

Or do you think there are only idiots developing C code?

How does things like OpenBSD get so secure? With a lot of code revisions by people that are good at catching problems. And even they have problems sometimes.

Your comparison with a knife is false, I can have multiple languages in my development machine without a big burden, as opposed to carry a lot of specialized cutting equipment.

So is Java/Python/Go a dull knife? Let's try something then, create a Web application in C as fast as it's doable with these languages and as safe as them.

-----


Your analogy suggests that "safer languages" are like crappier versions of C. I don't think that assertion is well supported.

-----


I think I qualified my analogy correctly. For general purpose, high-performance efficiency, you can't beat a knife. However, there are tons of specific applications where a tool other than a knife is preferred. That's the idea behind the phrase "the right tool for the job".

I wouldn't say a hatchet or a machete is a "crappier version" of a knife. Surely a hatchet is much better suited for chopping down a tree, for example. On the other hand, a knife would be very inefficient at the job, even if it could get the job done eventually. However, a hatchet is arguably less safe than a knife for many kinds of jobs, and a knife for hatchet-jobs, etc.

So really I guess my point was the idea of a "safer" language is dumb, because not every tool is "safe" for every job, and not every job is suitable for a "safe" tool.

-----


> the purpose it was designed for: cutting things.

The point of the parent is use the correct tool. Most of time people don't need to cut things, they just need to spread some butter.

-----


> However, it is also extremely inefficient at the purpose it was designed for: cutting things.

... So you're saying that C was designed for string handling?

> When wielded correctly it is still safe and efficient

You do realize that even the most skilled chefs have 'battle-scars', right? Your analogy falls on its face in this respect.

-----


Obviously strcpy is dangerous, that's why I copy all my strings by hand with:

  while(*dest++ = *src++);

-----


I really hope this was sarcasm. But if not...

There's nothing here to prevent a buffer overrun. If your src doesn't end in 0, or your dest is too small, you'll be reading memory you shouldn't and/or obliterating memory past your dest buffer. Your method is pretty much on par with an inlined strcpy.

-----


That's the joke

-----


The method is exactly an inlined strcpy.

-----


I don't always copy strings, but when I d8$#@C11&C^C^CSegmentation Fault

-----


Develop your c code in OpenBSD. The linker admonishes you any time you use unsafe string functions.

     warning: strcpy() is almost always misused, please use strlcpy()

-----


By default, Microsoft's C compiler will also give you warnings for unsafe functions. At least, it did the last time I used it a few years ago.

-----


It still does. Microsoft also banned a lot of C functions from usage internally [1]. For codebases that need to build in VC and other compilers I'm not yet sure how to really solve this apart from _CRT_SECURE_NO_WARNINGS.

[1]: http://msdn.microsoft.com/library/bb288454.aspx

-----


How about just taking BSD's functions and using them? strlcpy, strlcat, snprintf, etc. are all easily portable and libraries probably already exist for MS's compiler.

-----


The thing I didn't like about Microsoft's approach is that they also flagged some of the safer C functions, and introduced a new bunch of non-standard functions, the *_s functions. Those functions were eventually added to the C11 standard at Microsoft's suggestion, but until that point the MS C compiler would admonish programmers to write unportable code.

-----


(Not a C person here, but I'll ask anyway)

What should I use instead of these things if they're so dangerous?

-----


Almost every one has a n version you should use, and their man pages will tell you that.

strcpy -> strncpy (or strlcpy on BSD)

strcat -> strncat (or strlcat on BSD)

sprintf -> snprintf (but still watch out for printf format attacks)

gets -> something else entirely. The man page says "programs should NEVER use gets()".

-----


They told me if I used the n version I'd be safe. They told me the risks were tiny. That all we had to do was practice safe counting.

They told me that... ˚sob˚ but they were wrong.

-----


Hi, Is there any resource on Web or even any book that documents all the risks. I had once seen a talk given by you .. was good !! Any other such resources out there ??

-----


I like _The Art of Software Security Assessment_ for this.

-----


Good for laughs. Thanks. Now the serious follow up: Ok, what else should someone do?

Programs (often) handle text. Apparently, that pretty much means you're fucked. So what is a reasonable way to write such programs?

-----


Make damned sure you know what you're doing. That means making sure you have enough memory allocated to avoid overflows, and that any input is sanitized before putting it down. Meaning, if you're using a function that's expecting a null terminated string, make SURE it's null terminated before copying. Or that you know the exact length to pass into a length specified function.

The problem isn't necessarily the functions themselves, it's coders who make assumptions that don't pan out to be true.

-----


Do all of your string work with these guys:

    struct string {
      char *str;
      unsigned length;
    }

-----


Let's assume your string struct is solid. Then does that mean you can safely use it with `printf, fprintf, sprintf` (e.g. printf("%s", string->value)? Or must you also write custom versions of those functions? How deep does this rabbit hole go?

-----


You don't have to write custom versions of any of those functions; just use the char pointer in the struct instead of a bare char pointer. Keeping track of the length of your strings gives an easy way to provide the 'n' in all of those 'n' functions, and has other advantages besides. But the use of such a struct in and of itself, of course, provides no guarantees of safety. There is no such thing in C anyway :)

-----


You'd probably want

    "%.*s"
or possibly even

    "%*.*s"
if you want it space padded. In principle you can bound your space usage and avoid an snprintf with such constructs; in practice, it's probably better to still use snprintf (if you're using standard-library string functions at all).

-----


If you're able, don't treat text as zero-terminated char arrays. Ideally, you'd have a well fleshed-out library for encoding-aware ropes.

-----


Which libraries do you recommend?

-----


Unfortunately, I don't know of one. My recent C work has worked with text only in a very limited capacity (parsing and building packets in an ascii format - for the later, vectorized write buffers are a poor-man's ropes).

Edited to add:

Apparently there is this: http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/cordh...

-----


I recommend bstring for length-prefixed strings in C:

http://bstring.sourceforge.net/

-----


Bstring relies on undefined behavior for security. Don't use it if you care about security.

-----


Keeping in mind that strncpy has it's own problems, like not null terminating the buffer if it would overflow.

-----


I guess the whole point is don't rely on null terminated strings in your code.

-----


This is why you should use strlcpy()!

-----


The point of the n is that you specify the maximum length that it's allowed to copy. It's slightly harder to mess that up than with regular strcpy.

-----


The n in strncpy describes to what size the destination buffer (not string) should be padded with '\0'.

This is useful for copying a string into a fixed size buffer that is sent over the network, to give an example. It's not what the programmer generally means when using strncpy.

Many programmers are surprised when they learn that strncpy() really writes 1M-strlen("abc") zeros in the 1M char array every time it's called...

-----


"The n in strncpy describes to what size the destination buffer (not string) should be padded with '\0'."

This is false.

From the man page: "The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated."

And the following code prints foo:ar on my system.

    char buffer[10];
    strcpy(buffer, "foobar");
    strcpy(buffer, "foo");
    printf("%s:%s\n", buffer, buffer+4);
Edited to add: huh, scratch that. Obvious error in above test :-P. Testing it with strncat like I had meant to, it seems it is in fact padded, not just (possibly) terminated. Interesting, and very worth knowing if you are trying to move a probably small string to a large buffer under time pressure.

-----


What is false? I'm not talking about the source string not being terminated when it's too long. That's obvious and there are plenty posts about it in this thread.

Not sure what you want to say with the example code. Maybe swap it for strncpy and strlcpy and see whether that matches your expectations?

-----


Yeah, my bad, had meant to use strncpy. My contention had been that it only zeroes the first following character (if that). On closer reading of the man page, it is in fact clear.

-----


The alternative to gets() is fgets(). In fact, I'm pretty sure the gets() function is completely deprecated in the C11 standard.

However, despite the n functions being generally safer, you're still propagating misinformation by touting them as secure alternatives.

The original use of the n functions was to manipulate strings in matters of fixed size arrays. If you don't know what you're doing and just blindly use strncpy() as a strcpy() replacement, you could end up truncating your strings.

OpenBSD's l functions, on the other hand, were specifically designed with security in mind.

-----


exactly.

-----


The alternatives or more descriptions are linked to at the bottom of the article:

* http://natashenka.ca/strcpy/

* http://natashenka.ca/strcat/

* http://natashenka.ca/sprintf/

* http://natashenka.ca/pickle/

* http://natashenka.ca/arithmetic/

-----


As somebody who did little other than C for just over a decade, my answer would be "FreePascal", which lets you do similar low level things, but has a few "safeties" built in. Objective C looks to be a little better with strings as well, but I'm not very familiar with it. (dabbled in iOS years ago)

The people who brought us the [in]famous "Why Pascal is not my favorite language" article would have done well to look at their own glass house.

OTOH, C does make a great portable assembler if you are using it to implement another language (which is exactly what we did at one of my jobs in the early 90s)

... Had to explain to my daughter this morning why I was laughing at the "abstinence" posters ...

-----


I haven't used pascal for closing in on 20 years, and don't miss it one bit.

For you younger people reading this who have never been exposed to pascel, go dig up that article and scroll down to section 2.1 and just think about that for a minute. Ask yourself 'is this the kind of computing environment I want to work in?'

-----


FYI: FreePascal has Dynamic Arrays that are automatically resized by the runtime, which addresses section 2.1.

2.4 - separate compilation was added in Turbo Pascal 4. (one could argue that the result is Modula, rather than Pascal - so be it)

2.2 - initialization of module data was added in Turbo Pascal 5. Yes, "static" data has to be at the module level instead of hidden within individual routines. Bug or feature? (let the jihad/crusade commence...)

As the commentary on http://c2.com/cgi/wiki?WhyPascalIsNotMyFavoriteProgrammingLa... points out, the critique was against the 1981 academic version of Pascal.

-----


For C: strncpy(), strncat(), snprintf() (or the non-standard asprintf()), and fgets(), respectively. I believe pickle is a Python thing.

-----


The sa[fn]e alternative to pickling your objects is to write your data into a well defined file format and read it back with stringent input checks.

-----


It's worth noting that strncpy doesn't always null-terminate strings (on some platforms), so strlcpy is preferable.

-----


Python, Ruby, Java... ;-)

-----


Serious question: Aren't the C-based problems simply hidden from the programmer there? That is, the problems still exist, but you can no longer address them, qua Python, Ruby, Java programmer. That seems worse, not better.

-----


Depends on implementation. CPython may have problems due to C bugs. Java is self-bootstrapping, though, and has no relation to C except for interfacing with external programs using C calling conventions. In this case problems are not hidden, they are truly not existing, except for problems introduced by other programs you interface with - but not your code.

-----


You're quite wrong regarding Java. Much of its standard library is implemented in C and C++, and there have been frequent security vulnerabilities found in the language that are a result of buffer overflows or similar memory corruption bugs within the underlying C/C++ implementation.

There are many, but here's one such example from last year: http://osvdb.org/show/osvdb/94336

-----


If you don't write C very often (I don't) and you want to see these things in action: https://microcorruption.com

I had no clue printf was problematic.

-----


In this case I don't think they are warning about format string vulnerabilities. The poster mentions sprintf (not printf) so presumably they are warning you about overflowing the destination buffer.

I'm also having a super fun time with the microcorruption challenges. Highly recommend.

-----


printf (and others in that family of functions) are only exploitable if you do something like `printf(user_controlled_str)` (possibly with extra arguments).

Basically, don't let the user control the very first argument (which would allow them to add format specifiers like %d or %x) and you're safe.

-----


Well, yea. This is exactly what you do in a few levels of microcorruption.

You can always say "dont do X and you'll be fine." But that's kind of like saying "don't point a gun at someone" and the gun will be completely harmless. That's the trick, isn' it? That seems to be the point of the "True bugs wait" site at least. It only takes one mistake.

-----


I agree, especially with things like strcpy and strcat, but printf is kind of a special case because it's a very, very simple rule to follow. Plus most of the time it's illogical to use it without a format specifier (or with user supplied ones).

-----


What are those ads referring to originally? Is this a campaign in the US? Is it publicly funded?

-----


Sexual abstinence. And yes IIRC they are publicly funded in some states. Worse, they either don't give accurate information about contraception or give no information at all.

Needless to say, these policies have proven to be counterproductive when it comes to actual teen pregnancy and STI rates.

-----


Not that the negative correlation between abstinence only programs and pregnancy + STI rates deters the people who push them. When you start to view public health policy through the lens of individual morality (if not piety in some cases), the actual effects of a given policy effectively become irrelevant next to the intent of the policymakers.

To the unfortunate consequence of many teenagers.

-----


Of course, because if they don't heed your awesome moral advice and get into trouble then you can blame them for it!

I wish it wasn't so easy to be a misanthrope.

-----


Ugh. That part makes me sickest of all.

-----


This shit was all over Texas when I was growing up--did some lasting damage to several folks I know. :(

-----


Isn't that against the separation of church and state? Unless it was carefully crafted not to mention anything religious?

-----


It's perfectly secular to advocate abstinence until legal union.

Evil, but secular.

-----


If you are interested to know more, see Penn and Teller's Bullshit! episode on Abstinence.

https://www.youtube.com/watch?v=EDOGQ5A8M0w

-----


They're a parody of ads promoting abstinence from sex (probably targeted at high school aged kids). It looks like a typical US campaign. I couldn't find the original ads, so I can't answer your last question.

-----


A lot of older pregnancy awareness campaigns were all about abstinence in the USA. It is only recently that people have realized it doesn't work and things have been changing to advocating condom use etc.

-----


It's not "older", it's "Republican". There are still states that predominantly teach abstinence (looking at you, Texas, https://www.dshs.state.tx.us/abstain/), and any mention of contraceptives as both a means to reduce the risks of pregnancy, and of STDs, are mostly at the teacher's discretion, rather than a mandatory part of the course work.

-----


Not a C guy. Why are these functions unsafe?

-----


Here, runtime, make some results and put them into this (character array) buffer I'm providing for you. Oh, the buffer wasn't big enough? Well, I'm sure the stuff after the buffer's end that you wrote over wasn't all that important, anyway. Probably just a few neighboring local variables that my function was storing nearby on the stack, or maybe the return address on the stack, or maybe the heap management data (block size field, free list pointer, ...) around the block of memory I allocated from the heap.

I wonder what the next pass of my loop will do now, or what will happen when this function returns???

-----


Because C strings are arrays of characters terminated by a null ('\0') character, and arrays in C don't have bounds checking and don't come with a length attached.

If you allocate a 10-element character array, it can hold strings of up to 9 characters (plus the null terminator). But, the library functions ("runtime") don't know how big it is.

So if you try to copy a 20-character string into that 10-element buffer, it will copy 21 characters. The first 10 will go into the array, and the next 11 characters will go... somewhere else. Depending on where in memory your array and other things are, something important will probably get overwritten with garbage.

-----


I would like C to have a native String type, and the primitives could be function pointers, replaceable in those cases when custom handling is needed (e.g. inside kernel). Object Pascal is sort like that.

-----


D has this. A lot of people assume that D is just C++ with some GC and some improvements, but it's really more like C with GC and some improvements -- including a native String type.

There's also a string module in the standard library that includes a lot of convenience methods, including ones for interoperating with C and for working with Unicode[1].

For someone like me with a background in dynamic languages like Python and Lua, as well as some background in C, D was a great fit. Unlike when I started learning C++, D felt like a very natural extension of C to include GC and lots of modern language features.

Lamentably, not many people are interested in D, and so aren't yet a lot of third-party libraries, and many of those that are abandoned. But the core language and standard library are great, and there's a nicely growing and incredibly fast web framework (vibe.d). And Facebook has started supporting the language. So hopefully it will start seeing some growth.

1. http://dlang.org/phobos/std_string.html

-----


I've gone down this route of thinking many times. Inevitably, as soon as I think of all of the features that I would want in C, I simply end up with a language that's not C any more... for precisely that reason. C isn't that kind of a language; it's a high-level assembly language and little more. Most of the things that C is lacking, it is by design, because of performance reasons and/or need for fine-grain control of the machine.

As another respondent mentioned, there are other languages that fill that need (C++, D, Rust, Nimrod), basically all of the systems languages that are designed to do C's job easier and safer (but probably not faster).

-----


You can always use something like bstring. It will always be compatible with other libraries that take a pointer and a length.

-----


Even though I don't think abstinence-only sex education is a good idea, it's strange that the true statement "only abstinence is 100% effective" is mocked.

Or are liberals going to start teaching an honest version of their view: "A combination of condom use and abortion when condoms fail, is 100% effective"?

-----


I've only sees "only abstinence is 100% effective" mocked from a policy perspective. It is true that abstinence is 100% effective on a personal level, but teaching it is remarkably ineffective at a population level. There is room to mock it on a personal level, by pointing out that we are willing to engage in far more dangerous activities without 100% guarantees on safety. 'Seatbelts fail, only not driving is 100% effective'.

-----


>I've only sees "only abstinence is 100% effective" mocked from a policy perspective. It is true that abstinence is 100% effective on a personal level, but teaching it is remarkably ineffective at a population level.

The phrase "only abstinence is 100% effective" is a slogan for teens, not a claim that only abstinence only sex education is 100% effective (which is clearly false).

>There is room to mock it on a personal level, by pointing out that we are willing to engage in far more dangerous activities without 100% guarantees on safety. 'Seatbelts fail, only not driving is 100% effective'.

It depends on how much a person wants to avoid having an abortion or unplanned pregnancy, and how much value they get out of sex.

-----


> The phrase "only abstinence is 100% effective" is a slogan for teens, not a claim that only abstinence only sex education is 100% effective

You don't have to claim that a stupid course of action is perfect to deserve mockery. Following the stupid course of action will suffice.

> It depends on how much a person...

No, the success of abstincence-only education as public policy does not depend on a single person's wants, desires, and incentives. It depends on the wants, desires, and incentives of an existing imperfect population.

Claiming that "our policy would work if only people were moral and rational in X, Y, and Z ways" is irrelevant if people are known to not be moral and rational in X, Y, and Z ways, which is indeed the case with respect to sex-ed. At the end of the day it either works to reduce teen pregnancy or it doesn't, and in this sense abstinence-only education doesn't work.

-----


>> The phrase "only abstinence is 100% effective" is a slogan for teens, not a claim that only abstinence only sex education is 100% effective (which is clearly false).

It's a slogan associated with a moralistic, backwards, prude, stupid and failed sex-ed program. It deserves to be mocked.

>> It depends on how much a person wants to avoid having an abortion or unplanned pregnancy, and how much value they get out of sex.

Hmm, one of the more important drives, if not the primary hard-wired drive in a human animal, gee, I wonder how much value people get out of it?

-----


> The phrase "only abstinence is 100% effective" is a slogan for teens, not a claim that only abstinence only sex education is 100% effective (which is clearly false).

You're misunderstanding the point -- "only abstinence is 100% effective" is mocked precisely because it is a remarkably bad way to get kids not to have premarital sex.

-----


The reason is that that statement is, in fact, a lie.

Effectiveness of any form of birth control is usually quoted as two numbers: an perfect-use rate, and a typical-use rate.

The perfect rate assumes that you are able to follow the instructions exactly every time. For example, perfect use of a hormonal pill means that you take it every single day, at the same time, without ever forgetting; perfect use of condoms means that you use a condom every time you have sex, before beginning sex, that you put it on correctly and that you stop immediately if it breaks; et cetera. Even the much-lambasted "withdrawal" and rhythm methods have really quite good efficacy, assuming you implement them perfectly.[0]

Of course, people aren't robots, especially when it comes to sex, and that's why we have typical-use statistics that reflect the reality of the situation: People forget to take the pill, or take it at the wrong time. People skip using the condom, just this once-- and forget about "pulling out". And people who were abstaining, well, don't.

It may be the case, if we ignore certain unpleasant factors, that abstinence, done perfectly, has 100% efficacy for preventing pregnancy. But we need only to glance at the statistics to see that, in the real world, held to the standard we hold any other procedure to, it is the very worst form of birth control anyone has come up with yet. And that makes your "true statement" nothing more than a bald-faced lie.

[0] Look it up. About 5% failure rates, only twice as bad or so as condoms.

-----


Promoting abstinence results in higher rates of teen pregnancies and STDs than pretty much every other policy. That's the reason for ridiculing it - far from 100%, it actually has a negative value, working against its stated goals.

-----


Didn't I see a Law & Order about a woman drugging men and using a tazer to stimulate ejaculation? There's no such thing as 100% effective (http://lesswrong.com/lw/mp/0_and_1_are_not_probabilities), though abstinence actually practiced (rather than simply intended) is certainly the most effective approach.

-----


That is really gross, can you at least add some trigger warnings next time?

-----


Apologies.

-----


100% effective? Just wait until your friends invite you to a Hackathon, and all promises will be broken that night..

-----


Nice - although I wish they would fix the bugs in those libraries, too.

-----


How do you mean? strcpy and friends aren't buggy - they work according to the spec, and you can't just go and change an API that literally billions of lines of code depend on. You can only provide new, better alternatives.

If you mean the buggy software that uses the unsafe C APIs (and is not careful enough), then, that's exactly what those posters are about.

-----


I'm pretty sure those posters are making fun of the thinking that says you can just use some replacements and magically be safe.

The 'safe' versions of the functions have their own risks too. No amount of use-this-thing is a replacement for conscientious programming and review.

-----


Many of the man pages for the function say "don't use them." OpenBSD let you link against "strcpy" but screams at you if you do.

Also, what's pickle? PS: don't type "man pickle" into the google, you won't like it.

-----


When I was working at a game dev studio on a game that partially took place in a city, we had an artist, looking for photo reference, type in "man hole" in the google image search.

The resulting photo reference, in addition to being rather NSFW, was not useful for the particularly game we were making.

-----


pickle is a (de-)serialization library for Python. It allows arbitrary code evaluation, so shouldn't be exposed to the outside world (for the same reason that we have JSON parsers and don't use JS eval() to parse JSON).

-----


Pickle is Python's native object serialization. Unpickling user inputs is executing arbitrary code.

-----


Not accurate, Python has multiple serialization libraries and there is nothing special about pickle. Python's internal serialization is 'marshal' and shouldn't be used by apps for other reasons

-----


anonymoushn said "object serialization". "marshal" doesn't serialize objects.

    >>> import marshal, cPickle
    >>> x = object()
    >>> marshal.dumps(x)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: unmarshallable object
    >>> cPickle.dumps(x)
    'ccopy_reg\n_reconstructor\np1\n(c__builtin__\nobject\np2\ng2\nNtRp3\n.'
That's a bit tongue-in-cheek, but it shows that the marshal serialization only handles a handful (I count 9) of built-in object types.

What's "special" about pickle is it's the default recommended serialization method. Quoting http://docs.python.org/2/library/marshal.html:

> "If you’re serializing and de-serializing Python objects, use the pickle module instead – the performance is comparable, version independence is guaranteed, and pickle supports a substantially wider range of objects than marshal."

-----


Probably the python memory serialization library, which is known to be really dangerous if you use on untrusted input. http://docs.python.org/2/library/pickle.html

-----


Considering the poster mentions serialization, I would say it's about this: http://docs.python.org/3/library/pickle.html

-----


https://wiki.python.org/moin/UsingPickle

-----


Googling for "python pickle" will provide more benign search results.

-----


Friends don't let friends program in C

-----


I would punch my friends if they tried to stop me.

-----


True bugs wait in haunted attics.

-----


I laughed way too hard at this.

-----




Guidelines | FAQ | Support | API | Lists | Bookmarklet | DMCA | Y Combinator | Apply | Contact

Search: