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

Fix potential buffer overflows when calling sprintf #1742

Merged
merged 3 commits into from
Dec 1, 2023

Conversation

szsam
Copy link
Contributor

@szsam szsam commented Apr 15, 2023

No description provided.

@github-actions
Copy link

github-actions bot commented Apr 15, 2023

Build size and comparison to main:

Section Size Difference
text 377632B 16B
data 940B 0B
bss 63492B 0B

@minacode
Copy link
Contributor

Welcome to InfiniTime! 😊 I think it would be helpful if you write a little description about the motivations of the changes you made.

@Avamander
Copy link
Collaborator

These aren't overflows, truncations at best and modulo is relatively quite expensive.

The other parts, would be very nice if you would explain them.

szsam

This comment was marked as outdated.

@szsam szsam force-pushed the fix-overrunning-write branch from a4a5693 to fdf24db Compare April 21, 2023 03:41
@szsam
Copy link
Contributor Author

szsam commented Apr 21, 2023

A recent commit introduces a real one-byte buffer overflow.

char buffer[16];
if (times.hours == 0) {
sprintf(buffer, "#%2d %2d:%02d.%02d\n", i + 1, times.mins, times.secs, times.hundredths);
} else {
sprintf(buffer, "#%2d %2d:%02d:%02d.%02d\n", i + 1, times.hours, times.mins, times.secs, times.hundredths);
}

The format str "#%2d %2d:%02d:%02d.%02d\n" requires 17 bytes, but the buffer length is only 16. This is fixed in this PR.

Copy link
Member

@FintasticMan FintasticMan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that replacing sprintf with snprintf is necessarily a good idea. I believe that because it adds an overhead and that, with the current configuration, I don't think it does anything if it detects an overflow, we shouldn't use it.

src/displayapp/screens/settings/SettingDisplay.cpp Outdated Show resolved Hide resolved
src/displayapp/screens/StopWatch.cpp Outdated Show resolved Hide resolved
@szsam
Copy link
Contributor Author

szsam commented Apr 27, 2023

I don't think that replacing sprintf with snprintf is necessarily a good idea. I believe that because it adds an overhead and that, with the current configuration, I don't think it does anything if it detects an overflow, we shouldn't use it.

I agree that snprintf adds overhead. However, when snprintf(buffer, bufsz, fmt, ...) detects an overflow, it will write at most bufsz-1 characters, effectively preventing buffer overflow.

That said, if you insist on using sprintf, I will change the code and use it.

Copy link
Member

@FintasticMan FintasticMan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After looking into the overhead that snprintf adds, I've come to the conclusion that it is fine to use it over sprintf as an added layer of safety. We should of course still make sure that our values can never be higher than what we expect and that our buffers are big enough.

For some reason changing the format specifier macro to PRIu16 fixes the issue I mentioned before. Once that is fixed, I'm willing to get this merged.

@FintasticMan FintasticMan requested a review from a team November 28, 2023 22:24
1. Replace sprintf with snprintf, which is safer
2. An unsigned int or unsigned long int requires 11 bytes to print
   (including the null terminator)
3. Use PRIu16 macro to print uint16_t
4. Format string "#%2d %2d:%02d:%02d.%02d\n" in
   StopWatch::stopLapBtnEventHandler() requires at least 17 bytes.
   The 16-byte buffer would clearly be overrun if sprintf were used.
Given that 2^16 / 1000 is 65, we can make the buffer only 3 chars.
so that it's just as long as with the hour.
@szsam szsam force-pushed the fix-overrunning-write branch from 442d875 to 8e17945 Compare December 1, 2023 04:46
@szsam
Copy link
Contributor Author

szsam commented Dec 1, 2023

@FintasticMan Rebase done.

Copy link
Contributor

@NeroBurner NeroBurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@NeroBurner NeroBurner merged commit 42fcb99 into InfiniTimeOrg:main Dec 1, 2023
7 checks passed
@JF002 JF002 added this to the 1.14.0 milestone Dec 10, 2023
@Machiry
Copy link

Machiry commented Mar 25, 2024

Hello @FintasticMan, @Avamander, @NeroBurner ,

My name is Aravind Machiry, Assistant Professor at Purdue's ECE Department.

Thank you for considering this pull request. This pull request was the result of our on-going research work (along with @szsam) to improve the security and quality of open-source embedded projects.

In addition to scanning codebases with CodeQL, we are also doing a short (~4 minutes) survey to understand the use of static analysis tools like gcc -Wall and CodeQL in embedded software projects.

It would greatly benefit our research if you could fill this anonymous survey: https://purdue.ca1.qualtrics.com/jfe/form/SV_0OnXfr5plPe1QCa

Thank you,
Aravind

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants