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

IKOS should tolerate snprintf(NULL, 0, ...) #221

Open
szhorvat opened this issue Jul 27, 2023 · 4 comments
Open

IKOS should tolerate snprintf(NULL, 0, ...) #221

szhorvat opened this issue Jul 27, 2023 · 4 comments
Labels
C-false-positive Category: False Positive L-c Language: C

Comments

@szhorvat
Copy link

szhorvat commented Jul 27, 2023

ikos claims that the following C program is unsafe because of the null pointer passed to snprintf():

#include <stdio.h>

int main(void) {
    snprintf(NULL, 0, "%d", 123);
    return 0;
}

However, according to cppreference, when the second argument is 0, the first argument is allowed to be NULL.

https://en.cppreference.com/w/c/io/fprintf

If bufsz is zero, nothing is written and buffer may be a null pointer, however the return value (number of bytes that would be written not including the null terminator) is still calculated and returned.

We use this feature to determine the number of characters that would be written before actually writing them.

@ivanperez-keera
Copy link
Collaborator

I could be wrong, but at first glance I think we'd need to change:

case ar::Intrinsic::LibcSnprintf: {
return {this->check_null(call, call->argument(0), inv),
this->check_null(call, call->argument(2), inv)};
}

so that this->check_null(call, call->argument(0), inv) is only included when this->_lit_factory.get_scalar(call->argument(1)); is not zero. There may be several cases that we'd have to consider, such as it not being zero but being a variable (which may contain the value zero) and so on.

@arthaud
Copy link
Member

arthaud commented Nov 29, 2023

Maybe handling the special case of argument 1 being the 0 constant would be fine for now since that seems like a common use case.

@ivanperez-keera ivanperez-keera changed the title ikos should tolerate snprintf(NULL, 0, ...) ikos should tolerate snprintf(NULL, 0, ...) Dec 18, 2023
@ivanperez-keera ivanperez-keera changed the title ikos should tolerate snprintf(NULL, 0, ...) IKOS should tolerate snprintf(NULL, 0, ...) Dec 18, 2023
ivanperez-keera added a commit to ivanperez-keera/ikos that referenced this issue Sep 24, 2024
IKOS currently considers that the first argument of snprintf should
never be null. However, a first argument null is allowed when the second
argument is zero.

This commit introduces a check for that second value; only when it is
not the literal zero is the first argument checked. This check is not
perfect: the second argument could also be a variable with the value or
function call that returns zero. However, since passing the literal zero
is the most common scenario, we check for that case for now.
@ivanperez-keera
Copy link
Collaborator

I've just pushed to a branch what I consider may be a possible implementation. I have not tried to compile it on my machine, but I think it should be pretty close. Feel free to check it and point out any issues you see. It's possible that there's a simpler way to check for the argument to be zero than what I'm doing.

ivanperez-keera added a commit to ivanperez-keera/ikos that referenced this issue Sep 25, 2024
ivanperez-keera added a commit to ivanperez-keera/ikos that referenced this issue Sep 25, 2024
ivanperez-keera added a commit to ivanperez-keera/ikos that referenced this issue Sep 25, 2024
IKOS currently considers that the first argument of snprintf should
never be null. However, a first argument null is allowed when the second
argument is zero.

This commit introduces a check for that second value; only when it is
not the literal zero is the first argument checked. This check is not
perfect: the second argument could also be a variable with the value or
function call that returns zero. However, since passing the literal zero
is the most common scenario, we check for that case for now.
@ivanperez-keera
Copy link
Collaborator

ivanperez-keera commented Sep 25, 2024

I've placed a first attempt at fixing this issue here:

ivanperez-keera@e31c16b

I haven't tried it yet, but it does compile.

I feel like there may be a simpler way of checking whether the value is the literal zero, and I'm just not seeing it (it's just lack of familiarity with all of IKOS). I could also check whether it's a variable and it's zero, and it seems like that should not be hard to do.

@arthaud is what I'm doing too far off?

ivanperez-keera added a commit to ivanperez-keera/ikos that referenced this issue Sep 25, 2024
IKOS currently considers that the first argument of snprintf should
never be null. However, a first argument null is allowed when the second
argument is zero.

This commit introduces a check for that second value; only when it is
not the literal zero is the first argument checked. This check is not
perfect: the second argument could also be a variable with the value or
function call that returns zero. However, since passing the literal zero
is the most common scenario, we check for that case for now.
ivanperez-keera added a commit to ivanperez-keera/ikos that referenced this issue Sep 25, 2024
IKOS currently considers that the first argument of snprintf should
never be null. However, a first argument null is allowed when the second
argument is zero.

This commit introduces a check for that second value; only when it is
not the literal zero is the first argument checked. This check is not
perfect: the second argument could also be a variable with the value or
function call that returns zero. However, since passing the literal zero
is the most common scenario, we check for that case for now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-false-positive Category: False Positive L-c Language: C
Projects
None yet
Development

No branches or pull requests

3 participants