frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

OpenCiv3: Open-source, cross-platform reimagining of Civilization III

https://openciv3.org/
472•klaussilveira•7h ago•116 comments

The Waymo World Model

https://waymo.com/blog/2026/02/the-waymo-world-model-a-new-frontier-for-autonomous-driving-simula...
811•xnx•12h ago•487 comments

Show HN: Look Ma, No Linux: Shell, App Installer, Vi, Cc on ESP32-S3 / BreezyBox

https://github.com/valdanylchuk/breezydemo
157•isitcontent•7h ago•17 comments

Monty: A minimal, secure Python interpreter written in Rust for use by AI

https://github.com/pydantic/monty
155•dmpetrov•7h ago•67 comments

How we made geo joins 400× faster with H3 indexes

https://floedb.ai/blog/how-we-made-geo-joins-400-faster-with-h3-indexes
31•matheusalmeida•1d ago•1 comments

A century of hair samples proves leaded gas ban worked

https://arstechnica.com/science/2026/02/a-century-of-hair-samples-proves-leaded-gas-ban-worked/
91•jnord•3d ago•12 comments

Dark Alley Mathematics

https://blog.szczepan.org/blog/three-points/
50•quibono•4d ago•6 comments

Show HN: I spent 4 years building a UI design tool with only the features I use

https://vecti.com
260•vecti•9h ago•122 comments

Show HN: If you lose your memory, how to regain access to your computer?

https://eljojo.github.io/rememory/
207•eljojo•10h ago•134 comments

Microsoft open-sources LiteBox, a security-focused library OS

https://github.com/microsoft/litebox
328•aktau•13h ago•158 comments

Sheldon Brown's Bicycle Technical Info

https://www.sheldonbrown.com/
327•ostacke•13h ago•86 comments

Hackers (1995) Animated Experience

https://hackers-1995.vercel.app/
411•todsacerdoti•15h ago•219 comments

PC Floppy Copy Protection: Vault Prolok

https://martypc.blogspot.com/2024/09/pc-floppy-copy-protection-vault-prolok.html
22•kmm•4d ago•1 comments

An Update on Heroku

https://www.heroku.com/blog/an-update-on-heroku/
337•lstoll•13h ago•241 comments

Show HN: R3forth, a ColorForth-inspired language with a tiny VM

https://github.com/phreda4/r3
52•phreda4•6h ago•9 comments

Delimited Continuations vs. Lwt for Threads

https://mirageos.org/blog/delimcc-vs-lwt
4•romes•4d ago•0 comments

How to effectively write quality code with AI

https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/
195•i5heu•10h ago•144 comments

I spent 5 years in DevOps – Solutions engineering gave me what I was missing

https://infisical.com/blog/devops-to-solutions-engineering
115•vmatsiiako•12h ago•38 comments

Learning from context is harder than we thought

https://hy.tencent.com/research/100025?langVersion=en
152•limoce•3d ago•79 comments

Understanding Neural Network, Visually

https://visualrambling.space/neural-network/
244•surprisetalk•3d ago•32 comments

I now assume that all ads on Apple news are scams

https://kirkville.com/i-now-assume-that-all-ads-on-apple-news-are-scams/
996•cdrnsf•16h ago•420 comments

Introducing the Developer Knowledge API and MCP Server

https://developers.googleblog.com/introducing-the-developer-knowledge-api-and-mcp-server/
25•gfortaine•5h ago•3 comments

FORTH? Really!?

https://rescrv.net/w/2026/02/06/associative
45•rescrv•15h ago•17 comments

I'm going to cure my girlfriend's brain tumor

https://andrewjrod.substack.com/p/im-going-to-cure-my-girlfriends-brain
67•ray__•3h ago•28 comments

Evaluating and mitigating the growing risk of LLM-discovered 0-days

https://red.anthropic.com/2026/zero-days/
38•lebovic•1d ago•11 comments

Show HN: Smooth CLI – Token-efficient browser for AI agents

https://docs.smooth.sh/cli/overview
78•antves•1d ago•59 comments

How virtual textures work

https://www.shlom.dev/articles/how-virtual-textures-really-work/
30•betamark•14h ago•28 comments

Female Asian Elephant Calf Born at the Smithsonian National Zoo

https://www.si.edu/newsdesk/releases/female-asian-elephant-calf-born-smithsonians-national-zoo-an...
7•gmays•2h ago•2 comments

Show HN: Slack CLI for Agents

https://github.com/stablyai/agent-slack
41•nwparker•1d ago•11 comments

Evolution of car door handles over the decades

https://newatlas.com/automotive/evolution-car-door-handle/
41•andsoitis•3d ago•62 comments
Open in hackernews

Ratatoi is a C libary that wraps stdlib's strtol (as atoi does), but it's evil.

https://github.com/rept0id/ratatoi
31•rept0id-2•8mo ago

Comments

rept0id-2•8mo ago
Ratatoi is a C libary that wraps stdlib's strtol (as atoi does), but it's evil.

If an overflow is detected, it calls abort(), you crash and get Aborted (core dumped).

This way, you prioritize memory safety over silently running in a wrong state, without needing to call strtol and check errors manually everywhere.

timewizard•8mo ago
"This way, you open yourself up to DDoS attacks, instead of just handling your own errors correctly."
kstrauser•8mo ago
I prefer this approach. It's kind of like using `.expect()` or `.unwrap()` in Rust when there's no plausible way the call should fail. Like if my program writes out a JSON file and then reads it back in, and the file isn't value JSON, panicking is a reasonable way to deal with the situation. Someone the world got itself into a strange state I can't reasonably recover from.

Well, same here. If you're using strtol on data that must be well-formed, and it's not, and you're at an earlier stage of startup like parsing the config file, go ahead and blow up. That's almost certainly better than plowing ahead with invalid data.

LukeShu•8mo ago
> Like if my program writes out a JSON file and then reads it back in, and the file isn't value JSON, panicking is a reasonable way to deal with the situation.

Like how if I hit ctrl-C at just the right moment during the build, the next time I build, cmake will segfault and I have to delete the build directory.

threeducks•8mo ago
I think strtol is just a badly designed function. The return value should have been an error code and the actual long should have been "returned" via a pointer. Checking the return value is much easier than checking endptr and errno and remembering to set errno before calling strtol.

The fact that the strtol example in the manual is 50 lines long, of which most is error handling, speaks for itself. https://man7.org/linux/man-pages/man3/strtol.3.html#:~:text=...

That being said, I can't imagine many applications where crashing is a good solution.

wahern•8mo ago
OpenBSD added strtonum to <stdlib.h>. It's quite opinionated, but fits the usage patterns OpenBSD developers prefer.

> 50 lines long, of which most is error handling

That's a little exaggerated considering the example is an entire C program, including main. It's more like 14 lines, ignoring the '\0' check (which isn't necessary if you don't want to parse additional items), and even that includes whitespace and stderr logging.

I agree the biggest headache is reliance on errno and the nuanced--albeit conventional, consistent[1], and documented--semantics of only setting errno on error. Some POSIX APIs, at least those defined from scratch (e.g. pthreads, as opposed to incorporated common extensions) prefer returning the error code directly as you recommend. But this would technically only save you a single line, though it might save alot of confusion about semantics.

However, in this case I might keep returning the value directly and take an error pointer, similar to OpenBSD's strtonum. Otherwise you would need separate routines for char, short, int, long, and long long. Though there's still the issue of unsigned integers, and using _Generic it might be possible to at least hide all the type-specific variants behind a single interface.

And there's still the issue of needing to check for trailing garbage, or dropping the ability to use the interface inline with other parsing code. There's alot of dimensions to the problem. Parsing integers may be conceptually simple[2], but designing an interface that's easy to integrate into applications across a variety of contexts is much less simple.

[1] Consistent across libc interfaces, excepting those that may invoke syscalls internally, like printf, where errno may be incidentally modified even on success.

[2] I personally often prefer to just write a simple loop to manually parse integers. It's sometimes easier to integrate the desired error checking inline, or even elide it altogether (garbage-in, garbage-out).

roelschroeven•8mo ago
> conventional, consistent[1], and documented--semantics of only setting errno on error.

From that man page:

> The implementation may also set errno to EINVAL in case no conversion was performed (no digits seen, and 0 returned).

There are error cases where the implementation may set errno to EINVAL. There's not even a guarantee. I did a quick test. errno is only set if you pass an invalid base, or if the string does contain a number but it is out of range. If you pass a string which doesn't even remotely look like a number, errno is not set. You have to check endptr.

  #include <errno.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  int main(void)
  {
    const char *s = "this is not a number";
    printf("strtol(\"%s\")\n", s);
    errno = 0;
    long a = strtol(s, NULL, 10);
    printf("errno: %d; strerror: %s\n", errno, strerror(errno));
    printf("result: %d\n", a);
    return 0;
  }
Output:

  strtol("this is not a number")
  errno: 0; strerror: Success
  result: 0
https://godbolt.org/z/TbEKss8zM

That's just rubbish design. In what is in my opinion the most common error case, namely that the string doesn't represent a number while you expect that it does, errno is not set.

spyrja•8mo ago
Personally I'd just go the wrapper approach and ignore errno entirely.

  #include <assert.h>
  #include <ctype.h>
  #include <limits.h>
  #include <stdbool.h>
  #include <stdint.h>
  #include <stdlib.h>

  bool copy_str_to_long_long(const char* str, long long* ptr) {
    while (isspace(*str))
      ++str;
    if (*str == 0)
      return false;
    char* parsed = NULL;
    long long value = strtoll(str, &parsed, 0);
    while (isspace(*parsed))
      ++parsed;
    if (*parsed != 0)
      return false;
    *ptr = value;
    return true;
  }

  long long str_to_long_long(const char* str) {
    long long result;
    assert(copy_str_to_long_long(str, &result));
    return result;
  }

  bool copy_str_to_long(const char* str, long* ptr) {
    long long buffer;
    if (!copy_str_to_long_long(str, &buffer) || buffer < LONG_MIN || buffer > LONG_MAX)
      return false;
    *ptr = buffer;
    return true;
  }

  long str_to_long(const char* str) {
    long result;
    assert(copy_str_to_long(str, &result));
    return result;
  }

  /*
    ...define copy_str_to_short, copy_str_to_int32, etc...
  */
gpderetta•8mo ago
C can actually return structs by value and small structs are actually handled quite efficiently in some ABIs, so a pair result/error would be quite convenient although I guess not idiomatic.
PaulDavisThe1st•8mo ago
> The return value should have been an error code and the actual long should have been "returned" via a pointer.

Oh, you mean like:

    int ret = sscanf (str, "%d", &value);

?
sltkr•8mo ago
Yes, that API is actually great, but the problem with (s)scanf() is that reading an invalid value is undefined behavior. So you can't use it if you don't already know the result fits in &value, which is exactly the situation where you'd use strtol() instead.
CamperBob2•8mo ago
Presumably 'undefined behavior' means you'll get an undefined int value back -- which you will (of course) range-check -- not that it will wipe out the next 600KB of memory starting at &value or do something similarly hazardous.
roelschroeven•8mo ago
No, that's very much not what undefined behavior means. Undefined Behavior (the man page on my system actually capitalizes both words) means that there are no guarantees at all about the behavior of the whole program. It can very much wipe out whole chunks of memory, or crash (not necessarily in or around the sscanf call), or get stuck in an infinite loop, or whatever.
PaulDavisThe1st•8mo ago
From the man page on my system:

> Use of the numeric conversion specifiers produces Undefined Behavior for invalid input. See C11 7.21.6.2/10 ⟨https://port70.net/%7Ensz/c/c11/n1570.html#7.21.6.2p10⟩. This is a bug in the ISO C standard, and not an inherent design issue with the API. However, current implementations are not safe from that bug, so it is not recommended to use them. Instead, programs should use functions such as strtol(3) to parse numeric input. This manual page deprecates use of the numeric conversion specifiers until they are fixed by ISO C.

CamperBob2•8mo ago
If the CRTL maintainers don't care, why should I? Such behavior is broken, not "undefined."

As the other poster points out, the bug is in the spec, and I'd be astonished if the library function itself actually misbehaves with any given input.

roelschroeven•8mo ago
The bug is in the spec, but as the other pointer also points out:

> However, current implementations are not safe from that bug, so it is not recommended to use them. Instead, programs should use functions such as strtol(3) to parse numeric input. This manual page deprecates use of the numeric conversion specifiers until they are fixed by ISO C.

In other words, sscanf itself is not safe to use for numeric conversions.

Why should you care? Depends. Do you care about writing correct programs? If not, there's no need to care.

duneroadrunner•8mo ago
So I don't write much C code these days, but I recently encountered strtol() again and am I mistaken or does the interface also violate const correctness? I mean it takes a const char* as the first parameter and then gives you back a (non-const) char* potentially pointing into the same string, right? Like, does strtol() get a pass because it's old, or is const correctness (still) not generally a concern of C programmers?
jefftk•8mo ago
There are unfortunately a lot of old C library functions that violate const correctness. Consider dirname: https://www.jefftk.com/p/dirname-is-evil
spyrja•8mo ago
More than a few C library functions do that kind of thing. Like `strstr`, which takes const strings as arguments but returns a readily modifiable pointer to char. Const-correctness just wasn't on the top of the list when they standardized this stuff, I guess. (Heck, back in those days, most PROGRAMS for that matter weren't written with much care for it.)
wahern•8mo ago
It's a consequence of the peculiarity of C type semantics, which disallows implicit conversions of pointer-to-pointer to pointer-to-pointer-to-const. C23 6.5.16.1 EXAMPLE 3 explains why:

  const char **cpp; char *p;
  const char c = ’A’;
  cpp = &p;   // constraint violation
  *cpp = &c;  // valid
  *p = 0;     // valid

  The first assignment is unsafe because it would allow the 
  following valid code to attempt to change the value of the 
  const object c.
There are proposals on the table for C2y to redefine various APIs, including strtol, strchr, memcpy, etc, to preserve const correctness. Implementations might make use of _Generic (there are some issues there, though), newly specified language features, or possibly use internal extensions not available in the language proper, to accomplish this.
tedunangst•8mo ago
The idea is that if the input was not const, it's really inconvenient to get a const endptr back out. If your intention is to break your program, there are easier ways to do so than washing the pointer through strtol.
hedora•8mo ago
Crashing on error is almost always the right default behavior. If you do anything else by default, then you get in to the land of data corruption and security holes.

If you do this, and then find your thing crashes in production, then that means you didn't test it well enough.

Before someone mentions safety critical systems, consider the fact that the first apollo landing's computer crashed when it detected it was violating realtime bounds ("alarm 1201" means the OS detected CPU exhaustion + rebooted without clearing process state). At that point, it went into a reboot loop, and got close enough to the surface for Neil Armstrong to nudge the lander to a safe landing.

https://apollo11space.com/apollo-11-computer-problem/

bmink•8mo ago
I love the Apollo 11 computer stories but by today’s standards it was more of an MCU than a computer. And sure, in the embedded space it is true that in a lot of cases error recovery doesn’t make a whole lot of sense and it makes more sense to reset quickly.

But there are many systems today that take a long time to restart so you can’t just abort if you have a chance to recover.

AlotOfReading•8mo ago
The Apollo guidance computer specifically had a pretty unusual definition of "crashing" too. What it would do is save all the critical data, turn everything off, reinitialize the hardware, and restart all the jobs from designated reentry points. Very unlike what we think of as crashing. Regardless, a modern boot chain is much more complicated than anything the Apollo computers had to deal with, where rebooting (as opposed to the safe restart procedure above) simply involved setting the program counter to some default value.
lunar-whitey•8mo ago
The LM computer’s recovery routines for this scenario are more accurately described as “checkpoint/restore” than “crash” (as most people would understand the latter). The former technique is still used in high availability systems today.
lunar-whitey•8mo ago
This summary of events is incorrect. The LM guidance computer’s executive routines detected an overload (which occurred because Buzz Aldrin had left the rendezvous radar on) and continued to operate in a degraded state where lower priority work was not performed. These faults were reported and the landing proceeded with the computer remaining responsive to inputs despite the concerns the alarms produced. Armstrong’s control changes near the end of the descent were made for reasons unrelated to the rendezvous radar error.

Modern systems use more formal techniques to achieve the same goal: graceful degradation.

For a detailed account of computer operations during the Apollo 11 landing, you can read this analysis from an engineer who worked on the program:

https://www.doneyles.com/LM/Tales.html

ksherlock•8mo ago
Your errno checks aren't correct.

errno is only set on an error. It's not cleared on success. If errno was previously set, the function will always abort(). So you need to do something like:

    int saved_errno = errno;
    errno = 0;
    ....
    errno = saved_errno;
    return aInt;
ben0x539•8mo ago
Doesn't it set errno to 0 first thing?
ksherlock•8mo ago
ahh, you're right. It's still polite to save and restore though :)
rantouan•8mo ago
not bad, check my suggestion for pull request, above
kazinator•8mo ago
No ISO C standard library function sets errno to zero, but functions not in the standard library are not so obliged.

Functions that clobber errno to zero make it impossible to call several functions and use a nonzero value of errno to conclude that one or more of them went wrong.

If you don't think that such code is a good idea (for instance because you believe that every function that can fail should be checked for its specific error), then you probably have nothing against functions which clobber errno to zero.

rantouan•8mo ago
hello, errno is set to 0 first thing.

I added now a "/** * * */" separator to make it even more clear.

I don't know, but I like separating things like that, I think it's handy for cases like now that setting the errno was kind of mixed with vars initialization.

```

    errno = 0;

    char *strtolEndptr;
    ...

```

->

```

    errno = 0;

    /*** * * ***/

    char *strtolEndptr;
    ...
```

rantouan•8mo ago
For the restoring part, could you make a pull request please ? Open source strength is that we work together on things.
snarfy•8mo ago
pun driven development
cmovq•8mo ago
Interestingly, a complete implementation of strtol [1] is shorter than this wrapper. If you don't like strtol's API or error handling, just implement your own.

[1]: https://github.com/gcc-mirror/gcc/blob/master/libiberty/strt...

> If an overflow is detected, it calls abort()

An aside, but this doesn't detect overflows on Windows due to both long and int being 32 bits (you'd want strtoll for that).

kazinator•8mo ago
Where is it documented that atoi wraps strtol?
rantouan•8mo ago
https://www.gnu.org/savannah-checkouts/gnu/libc/index.html : The project website can be found here: https://sourceware.org/glibc

->

https://sourceware.org/ Links table on the left -> "GLIBC" button

->

https://sourceware.org/glibc/ Top menu -> "sources"

->

https://sourceware.org/glibc/sources.html "gitweb" link

->

https://sourceware.org/git/?p=glibc.git Top menu -> "tree" link

->

https://sourceware.org/git/?p=glibc.git;a=tree Tree -> "stdlib" link

->

https://sourceware.org/git/?p=glibc.git;a=tree;f=stdlib;h=93... Tree -> "atoi.c" row -> "raw" link

->

https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=stdli...

``` /* Convert a string to an int. / int atoi (const char nptr) { return (int) strtol (nptr, (char *) NULL, 10); } libc_hidden_def (atoi) ```

eqvinox•8mo ago
"long" is not guaranteed to be larger than "int", and in fact it isn't on 64-bit Windows. (Let alone 32-bit platforms in general.)

https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_m...

You need to use "long long" or "intmax_t" (and matching strtoll/strtoimax)

rantouan•8mo ago
overflow problems, which I try to avoid, start only if its bigger than int.

So I had assumed that in my case I'm alright. Do you see any change needed that I can't see ?

---

Maybe a good idea would had been to go by platform or architecture and use some macros to do the check only if it's really needed. What do you think of it ? How would you implement it ?

You can make a pull request as well.

eqvinox•8mo ago
If strtol reliably sets errno to ERANGE, you're fine (you'll get a compiler warning for "if (aLong < INT_MIN || aLong > INT_MAX) {" though, because it can never be true.)

I have no idea what the cross-platform reliability of strtol() is, regarding errno. Should be fine, I hope.