Live data from Hacker News

C Strings and my slow descent to madness

deusinmachina.net

201–210 of 329 posts

Re: C Strings and my slow descent to madness

#201

Earlier quoted context omitted.

I think this naming style should be considered obsolete. - This function will return the number of bytes, not of characters or codepoints. - str and len are both abbreviations, we should use full words when possible - We can also be more explicit about what the function does, it does not simply returns the string length, it counts characters (or bytes in this case) Here is how I would name it: u32 CountBytesInString(…

C isn't Java. Even Niklaus Wirth in Pascal, Oberon, and the like avoided naming their identifiers too long. 'GetStrSz()' is enough to achieve (most of) what you want, assuming certain naming conventions: - Makes it clear that this returns the number of bytes, assuming a naming convention where `sz` refers to size (in bytes) and `ln` refers to length (in some other unit which would be specified in the type). Note that…

Naming is extremely important, and while strlen is a very basic and hardly ambiguous example, consistency is key and I believe that good naming rules should be applied globally or at least at the framework level.

I think that full words and verbs are easier to read and avoid ambiguity.

I guess this is a matter of style and preference.

This anecdote reminds me of the Mutazt type, something I found in a new codebase I was asked to debug. I had to dig for almost an hour to find exactly what this type was.

Turns out it was a char*, a C string. Buried under 4-5 levels of abstractions.

Mutazt = Mutable ASCII Zero Terminal.

Re: C Strings and my slow descent to madness

#202
Pop quiz, which of these is safe, given "char buf[80]" and arbitrary user input in argv[1]?

    gets(buf);
    scanf("%s", buf);
    strcpy(buf, argv[1]);
    scanf("%80s", buf);
    strncpy(buf, argv[1], 80);
    snprintf(buf, 80, argv[1]);
----

The delightful answer is none of them. The first three have no bounds checking at all, meaning that they will happily overflow the buffer to an arbitrary extent (gets, at least, will usually trigger a warning on modern compilers). The next two have off-by-one errors: scanf will write a NUL byte out of bounds (and that's exploitable! https://googleprojectzero.blogspot.com/2014/08/the-poisoned-...) while strncpy will fail to NUL-terminate the string. The last one uses the right buffer length, but treats user input as a format string and can leak memory contents or produce arbitrary memory corruption with the %n format specifier.

C string handling practically invites off-by-one errors and horrible security practices out-of-the-box.

Re: C Strings and my slow descent to madness

#203
post #168

Earlier quoted context omitted.

I love how in every C code snippet on every comment on this thread, somebody got something wrong. I take it as a sign that it's probably best to avoid C as much as possible.

Any C compiler that isn't a trivial toy implementation will warn about that, so it's hardly a C gotcha.

clang and VC++ for x64 warn about this out of the box, but gcc seems to need -Wall.

Re: C Strings and my slow descent to madness

#204

Literally 25 years ago I was a beginner programmer and tried writing a .dll for Microsoft's Internet Information Server, which was relatively new at the time. (I hadn't so much as seen a Unix-based OS at the time, let alone understood CGI). C strings were mind boggling and frustrated me so much I simply gave up. Happily around the same time, MS introduced Active Server Pages and I was able to use that and never messe…

That is the most mind-boggling part of this saga to me. People have been using C since the 1970s. It's now 2023, and there still isn't an obvious solution to this other than suggestions that every team should write their own string library from scratch.

And apparently it all started with some genius deciding that using a single 0-byte at the end is so deliciously efficient and therefore obviously the way to go. We can't waste 4 bytes for the string length, that's out of the question. I think only the Pascal solution of having a single byte for the string length is worse.

Re: C Strings and my slow descent to madness

#205

> By default, Windows PowerShell .lnk shortcut is hardcoded to use the "Consolas" font Surely this is not the case for Japanese versions of Windows (or users with Japanese set as their display language?)

Yes, you can actual look at the full list from `HLKM\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont` (taken from my copy of Windows 10, bracketed comments mine):

    0       Lucida Console
    00      Consolas
    932     *MS ゴシック [MS Gothic for Japanese]
    936     *新宋体 [Simsun for simplified Chinese]
    949     *굴림체 [Gulimche for Korean]
    950     *細明體 [Windows MingLiU for traditional Chinese]
Note that there are actually two global defaults which only are differentiated by leading zeros. This is intentional and can be used to enable additional fonts; it is a common tweak for Korean (and probably other CJK) users to add a preferred font with a name 0949 or 00949 etc.

Re: C Strings and my slow descent to madness

#208

Earlier quoted context omitted.

On the contrary, I expected the Nintendo DS SDK to be well optimized, performance of memcpy can be critical on such a constrained hardware. And it was optimized, just not with the best tricks. I got the prefetching trick from Intel source code, except that I replaced the PLD instruction by a simple dummy load. And about strlen, you'd be surprised, some implems are very good, and some are not, depends on the compiler…

I think this expectation doesn't vibe with my understanding of how people used to think about embedded or consoles. You shipped them and they were done. The games industry was also often trying to ship quickly. Small teams too. Latest tweaks to memcpy or fine tuning or revisiting the finer points of an already adequate SDK is low priority. By contrast, many more people are updating optimizations to GCC or clang for a…

You're probably right about consoles, and I was surprised to be wrong, but I checked, just to be sure.

GCC and Clang are very nice compilers, but they are a different thing than the std lib. glibc, musl, the Windows C Runtime, iOS, Android, all have different implementations, sometimes outdated.

Re: C Strings and my slow descent to madness

#209

"We're not in Kansas any more, Toto" Or to paraphrase that "We're not in Python any more, and C is not Python". You know what sends me insane? Indentation and lack of fixed types in Python. But I don't have problems with C strings. Because I have grown to love and know C's string foibles just like the author will certainly not be driven insane by 'Python's shortcomings according to me'. The world is full of people wh…

There is no practical advantage to null terminated strings though.

It's not that they are "different", it's that they are extremely error prone and have poor performance for certain operations such as getting the length.

>But I don't have problems with C strings

Everyone thinks they are clever enough to use them and other parts of C without problems, and those people are the most dangerous.

Re: C Strings and my slow descent to madness

#210

Pop quiz, which of these is safe, given "char buf[80]" and arbitrary user input in argv[1]? gets(buf); scanf("%s", buf); strcpy(buf, argv[1]); scanf("%80s", buf); strncpy(buf, argv[1], 80); snprintf(buf, 80, argv[1]); ---- The delightful answer is none of them . The first three have no bounds checking at all, meaning that they will happily overflow the buffer to an arbitrary extent (gets, at least, will usually trigg…

Are you sure that strncpy does an out-of-bound write here? I believe it doesnt, but would give you an unterminated string in buf which is also... less than ideal (if the input is 80 non-null characters or longer).
Post reply on HN