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

CodeQL -- Actual fixes #2720

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

henrygab
Copy link
Contributor

@henrygab henrygab commented Jan 15, 2025

Many of the CodeQL bugs of type "Comparison between A of TypeA and B of wider type TypeB" were caused by having arithmetic within a for() loop's comparison clause. Not only were the operations redundant, but they could cause unintended consequences (e.g., integer promotion rules). Relatively simple to fix (use larger of two sizes for loop variable, compare unsigned vs. unsigned, etc.).

The other reason for many of these was that spiffs, in the definition of struct spiffs_t, defined field block_count of type uint32_t, but defined field free_cursor_block_ix to be of type spiffs_block_ix. In PM3, spiffs_block_ix is defined as uint16_t. Thus, a variable of type spiffs_block_ix cannot directly loop against block_count (potential infinite loops).

Inline "conversation"s added below, both to explain some changes, and to mark code that should have a second set of eyes review.

Code was previously performing arithmetic in
various loop check conditions.  Integer promotion rules could cause unintended comparisons.

`spiffs` defined `fs->block_count` as `uint32_t`, but defined `spiffs_page_ix` as `uint16_t`.  Various overflow checks detected by CodeQL and fixed by checking for those conditions before looping.
The compiler warning is incorrect.
Since `calloc()` zero's memory, can
remove redundant line setting value
to zero, giving quieter builds.
@@ -535,26 +535,61 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {

s32_t res = SPIFFS_OK;
spiffs_page_ix pix_offset = 0;
// Avoid arithmetic in loop conditions (integer promotion rules can cause unintended consequences)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please have second set of eyes review these checks.

@@ -114,8 +114,10 @@ static int EmSendCmdThinfilmRaw(const uint8_t *resp, uint16_t respLen) {
}

// Ensure that the FPGA Delay Queue is empty
uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3;
for (i = 0; i <= (fpga_queued_bits >> 3) + 1;) {
uint16_t fpga_queued_bits = FpgaSendQueueDelay >> 3;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

explicitly use unsigned values for the maths, and store back as uint16_t. This allows the for() loop to index on a variable of size uint16_t.

Copy link
Collaborator

Choose a reason for hiding this comment

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

good catch

keep_field_on = i < ndef_size + offset - max_rapdu_size;
aREAD_NDEF_n = 0;
param_gethex_to_eol("00b00000", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
aREAD_NDEF[2] = i >> 8;
aREAD_NDEF[3] = i & 0xFF;

// Segment_size is stuffed into a single-byte field below ... so error out if overflows
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If previous code ever had a segment_size greater than 0xFF, then the old code would have silently truncated the value. After review, this appeared to be incorrect behavior, and that there was an implicit assumption that segment_size would always be single-byte value.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Proper solution would not to use size_t but u32 and look into the ndef standard to handle larger than 0xFF sized segments?


// empty e_sector
for (size_t i = 0; i < items; i++) {
for (uint8_t j = 0; j < 2; j++) {
(*src)[i].Key[j] = 0xffffffffffff;
(*src)[i].foundKey[j] = 0;
// (*src)[i].foundKey[j] = 0; // calloc zero's these already
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, I cannot explain why CodeQL alerted on this line, and therefore cannot explain why its removal makes CodeQL happier. But, it's redundant since calloc() ensures memory is zero at allocation, so ... removal is OK.

Copy link
Collaborator

Choose a reason for hiding this comment

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

true , still shows that codeQL has false positives

@@ -245,7 +245,7 @@ static int ask_em410x_binary_decode(bool verbose, uint32_t *hi, uint64_t *lo, ui
else if (ans == -4)
PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x preamble not found");
else if (ans == -5)
PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x Size not correct: %zu", size);
PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x Size not correct: %zu", *size);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

size was a pointer to the size, not the size itself.

Copy link
Collaborator

Choose a reason for hiding this comment

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

good catch

This is supported for GCC >= version 13

See GCC bug 85487:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85487
0);
// traverse each page except for lookup pages
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block;
while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block + 1)) {
while (!restart && cur_pix < total_blocks_plus_one_page) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

this one says "cur_block + 1" vs "total_blocks_plus_one_page" ???

spiffs_block_ix bix = 0;
while (bix < fs->block_count) {
while (bix < block_count) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

is it really that block_count is large, or ?
block_count = 0, nothing happens,
if large number, the spiff_ok check should fail when trying to erase a block outside of existing once..

not sure how this would be a infinite loop?

uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3;
for (i = 0; i <= (fpga_queued_bits >> 3) + 1;) {
uint16_t fpga_queued_bits = FpgaSendQueueDelay >> 3;
fpga_queued_bits /= 8u;
Copy link
Collaborator

Choose a reason for hiding this comment

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

use the >>> 3 for consistency. Once upon a time we didn't want to trigger floats inside the arm code because of size.


// This allocates based on the size of a single item
_Static_assert(sizeof(sector_t) >= 18, "Unexpectedly small sector_t"); // if packed, would be 18
_Static_assert(sizeof(sector_t) == 24, "Sector_t used to be padded to 24 bytes?"); // not packed, so each entry must be 24 bytes
Copy link
Collaborator

Choose a reason for hiding this comment

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

This code looks more like debug code.

// ISSUE: C99 has no _Static_assert() ... was added in C11

PrintAndLogEx(WARNING, "word count was: %d, limiting to %d", now, EM4X50_NO_WORDS);
now = EM4X50_NO_WORDS;
}

if (now > 0) {

Copy link
Collaborator

Choose a reason for hiding this comment

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

this one can be " if (now) {

PrintAndLogEx(WARNING, "word count was: %d, limiting to %d", now, EM4X50_NO_WORDS);
now = EM4X50_NO_WORDS;
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

the proper fix would be not misusing the return status code and check it accordingly

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.

2 participants