Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

snprintf(3) is hard to get right for concatenating strings #804

Closed
alejandro-colomar opened this issue Dec 10, 2022 · 7 comments
Closed

Comments

@alejandro-colomar
Copy link
Contributor

alejandro-colomar commented Dec 10, 2022

len = snprintf(cgprocs + len, NXT_MAX_PATH_LEN - len, "/cgroup.procs");

if (nxt_slow_path(len >= NXT_MAX_PATH_LEN - len)) {

These two lines are very hard to get right. So much that I found a bug twice (#734 (comment)), in two different rewrites of that code, before it was finally fixed. The underlying problem is not in that code per se, but rather on the misdesign of string copying functions in the C library. There's no function that does the following operation:

"Copy from a (null-terminated) string into a null-terminated string with truncation, report truncation, and allow chaining calls to this function."

Okay, I'm being too picky. Let's loosen the requirement:

"Copy from a (null-terminated) string into a null-terminated string with truncation."

Nothing, the C standard library still doesn't have such a function. Only OpenBSD and a few other systems added strlcpy(3) to cover that hole, but it's a misdesigned function and anyway we can't use it.

Two sets of string copying functions that "copy from a (null-terminated) string into a null-terminated string with truncation" have been invented:

  • The Linux kernel added strscpy(9). However, it has issues: You can't chain that function easily. And of course, it's not available in user space.

  • OpenBSD added strlcpy(3) and strlcat(3). However, they also have issues: Detecting truncation is complex; they have serious performance issues; and you need to detect truncation after every call. And, we would need to depend on libbsd on GNU/Linux systems; we don't want that.

A better function, which has optimal performance, can be chained, and is difficult to misuse, is the following:

/* This code is in the public domain. */
char *
stpecpy(char *dst, char past_end[0], const char *restrict src)
{
    char *p;

    if (dst == past_end)
        return past_end;

    p = memccpy(dst, src, '\0', past_end - dst);
    if (p != NULL)
        return p - 1;

    /* truncation detected */
    past_end[-1] = '\0';
    return past_end;
}

I'll prepare a pull request that simplifies that code in the Isolation code, making it much simpler, faster, and safer.

@hongzhidao
Copy link
Contributor

Just wondering if there is an issue with the cgroup isolation?

@alejandro-colomar
Copy link
Contributor Author

alejandro-colomar commented Dec 10, 2022

Just wondering if there is an issue with the cgroup isolation?

No, the bug was fixed. This is just me wanting to remove complex code.

@ac000
Copy link
Member

ac000 commented Dec 11, 2022

Can you change the subject line of the issue to remove the unsafe word, unless you can actually point to a problem with them in their current form.

I think you are conflating 'unsafe' with 'hard to get right' which are not really the same thing.

@alejandro-colomar alejandro-colomar changed the title Unsafe calls to snprintf(3) snprintf(3) is hard to get right for concatenating strings Dec 11, 2022
@alejandro-colomar
Copy link
Contributor Author

Can you change the subject line of the issue to remove the unsafe word, unless you can actually point to a problem with them in their current form.

I think you are conflating 'unsafe' with 'hard to get right' which are not really the same thing.

Done. Sorry for any confusions :)

@hongzhidao
Copy link
Contributor

Feel free to reopen it if any issue is found.

@ac000
Copy link
Member

ac000 commented Nov 6, 2023

Hmm, not really completed.. where does that come from?, lets see...

@ac000 ac000 reopened this Nov 6, 2023
@ac000
Copy link
Member

ac000 commented Nov 6, 2023

Hmm, so we only have two options

"Completed"
and
"Not Planned"

That misses quite a wide gamut of possibilities...

Seems it's a relatively new thing. Can't immediately see a way of changing, adding new ones (like with issue labels...), oh well...

@ac000 ac000 closed this as completed Nov 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants