As already stated I don't have much time at hand, so I can't really get into this challange (honestly, currently I should be doing sth else, but some procrastination is fine), but here are my thoughts from looking at it for about 2 hours (taken all the few times i looked at it together):
calloc takes an size_t type, which is in the glibc unsigned, while cnt is signed. This means giving a negative number for cnt will result in a huge memory area being allocated (as it is converted to unsigned), but i < cnt would surely be false, so we have a huge memory area we can't access.
Also calloc checks for overflow for the multiplication of numElements * sizeElements, meaning you can't simply trick it to allocate a small area but access on large indices (and thereby write out of memory)
I already mentioned:
Which could have been exploited 20 years ago or so, but is off the table on modern systems
Is interesting, because 0 <= idx < ARR_LEN is equal to (0 <= idx) < ARR_LEN. (0 <= idx) is either 0 or 1, ARR_LEN is equal to 10, making this a tautology. So using this line of code, one can basically check any memory location if it is NULL, and with the rest of the function you can get at least some information off the state of the memory (basically by timing how long the operation takes you could guess the value written in a position, referenced by data + idx), which is a huge security flaw, but I don't think it's directly exploitable for the challange.
The more interesting occurance of this tautology is here:
Which basically let's you call free on any arbitrary memory location, which isn't NULL, and write NULL to it.
So yeah, maybe some if this is exploitable ([Only registered and activated users can see links. Click Here To Register...]), but everything further than this simple analysis would take me looking deeper than just the man pages for malloc/calloc/free, and I simply have no time for that.
Code:
data = calloc(cnt + 1, sizeof(*data));
Also calloc checks for overflow for the multiplication of numElements * sizeElements, meaning you can't simply trick it to allocate a small area but access on large indices (and thereby write out of memory)
I already mentioned:
Code:
for(int i=1; i < cnt + 1; i++){
Code:
if(!(0 <= idx < ARR_LEN) || data[idx] == NULL){exit(0);}
The more interesting occurance of this tautology is here:
Code:
if(0 <= idx < ARR_LEN && numbers[idx] != NULL){
free(numbers[idx]);
numbers[idx] = NULL;
So yeah, maybe some if this is exploitable ([Only registered and activated users can see links. Click Here To Register...]), but everything further than this simple analysis would take me looking deeper than just the man pages for malloc/calloc/free, and I simply have no time for that.