mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-09-11 18:29:22 -07:00
hf mad: fix aarch64 -Wstringop-overflow false positive in mad encode
GCC on aarch64 vectorizes the sector fill loop in parse_sector_ranges() into 16-byte NEON stores. When it versions the loop it loses the range relationship between count and max_sectors, and reports a 16-byte store into the last 8 bytes of sectors[40]. The code was correct; the guard was there. Does not reproduce on x86-64 gcc 14. Accumulate sectors in a uint64_t bitmask instead of an array, so there is no store for -Wstringop-overflow to mis-size on any target. Sector numbers are already validated to 1..39, so the bound check is no longer needed. Supersedes the sectors[48] padding, which only absorbs a 16-byte vector and would regress on wider ones. Side effect: duplicate sectors within a single --aid argument now dedupe instead of erroring (E103:1-3,2 encodes 1-3). Conflicts between different --aid arguments still error.
This commit is contained in:
+15
-12
@@ -501,9 +501,9 @@ static int CmdMADDecode(const char *Cmd) {
|
||||
|
||||
// --- Encode ---
|
||||
|
||||
// parse "1-3,5,7-9" into sector numbers, returns count or -1 on error
|
||||
static int parse_sector_ranges(const char *str, uint8_t *sectors, int max_sectors) {
|
||||
int count = 0;
|
||||
// parse "1-3,5,7-9" into a bitmask of sector numbers, returns count or -1 on error
|
||||
static int parse_sector_ranges(const char *str, uint64_t *sector_mask) {
|
||||
uint64_t mask = 0;
|
||||
const char *p = str;
|
||||
|
||||
while (*p) {
|
||||
@@ -541,10 +541,7 @@ static int parse_sector_ranges(const char *str, uint8_t *sectors, int max_sector
|
||||
PrintAndLogEx(ERR, "Sector " _YELLOW_("%ld") " is reserved for MAD directory", s);
|
||||
return -1;
|
||||
}
|
||||
if (count >= max_sectors) {
|
||||
return -1;
|
||||
}
|
||||
sectors[count++] = (uint8_t)s;
|
||||
mask |= (1ULL << s);
|
||||
}
|
||||
|
||||
p = end;
|
||||
@@ -553,7 +550,9 @@ static int parse_sector_ranges(const char *str, uint8_t *sectors, int max_sector
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
||||
*sector_mask = mask;
|
||||
return __builtin_popcountll(mask);
|
||||
}
|
||||
|
||||
static int CmdMADEncode(const char *Cmd) {
|
||||
@@ -601,16 +600,20 @@ static int CmdMADEncode(const char *Cmd) {
|
||||
memcpy(aid_str, val, 4);
|
||||
uint16_t aid_val = (uint16_t)strtoul(aid_str, NULL, 16);
|
||||
|
||||
uint8_t sectors[48] = {0};
|
||||
int nsectors = parse_sector_ranges(colon + 1, sectors, 40);
|
||||
uint64_t sector_mask = 0;
|
||||
int nsectors = parse_sector_ranges(colon + 1, §or_mask);
|
||||
if (nsectors <= 0) {
|
||||
PrintAndLogEx(ERR, "Invalid sector range in " _YELLOW_("'%s'"), val);
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
for (int s = 0; s < nsectors; s++) {
|
||||
uint8_t sno = sectors[s];
|
||||
for (uint8_t sno = 1; sno < 40; sno++) {
|
||||
|
||||
if ((sector_mask & (1ULL << sno)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sector_aids[sno] != 0) {
|
||||
PrintAndLogEx(ERR, "Sector " _YELLOW_("%d") " already assigned to AID " _YELLOW_("0x%04X"), sno, sector_aids[sno]);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
Reference in New Issue
Block a user