```free(): Invalid pointer``` when using ```uriParseSingleUriA``` and ```uriUriStringToUnixFilenameA```
b-carr opened this issue · comments
I'm experimenting with using the library and came across a strange bug. I started with this code:
#include <stdio.h>
#include <uriparser/Uri.h>
int main(void){
const char* test_uri = "file:/012345678901234567890123456789012345678";
UriUriA uri_data;
char* filename = (char*)calloc(strlen(test_uri)-6, 1);
const char* error_pos = NULL;
uriParseSingleUriA(&uri_data, test_uri, &error_pos);
uriUriStringToUnixFilenameA((const char*)test_uri, filename);
uriFreeUriMembersA(&uri_data);
free(filename);
exit(0);
}
which, when compiled with gcc v7.5.0 fails with message
free(): Invalid pointer
Aborted (core dumped)
I did some fiddling and found 2 ways to make the code work. First, by moving the call to uriFreeUriMembersA
before the call to uriUriStringToUnixFilenameA
, giving this code:
#include <stdio.h>
#include <uriparser/Uri.h>
int main(void){
const char* test_uri = "file:/012345678901234567890123456789012345678";
UriUriA uri_data;
char* filename = (char*)calloc(strlen(test_uri)-6, 1);
const char* error_pos = NULL;
uriParseSingleUriA(&uri_data, test_uri, &error_pos);
uriFreeUriMembersA(&uri_data);
uriUriStringToUnixFilenameA((const char*)test_uri, filename);
free(filename);
exit(0);
}
The second way to make it work is to replace the 6
with a 4
in the computation of the length of filename
, so this code:
#include <stdio.h>
#include <uriparser/Uri.h>
int main(void){
const char* test_uri = "file:/012345678901234567890123456789012345678";
UriUriA uri_data;
char* filename = (char*)calloc(strlen(test_uri)-4, 1);
const char* error_pos = NULL;
uriParseSingleUriA(&uri_data, test_uri, &error_pos);
uriUriStringToUnixFilenameA((const char*)test_uri, filename);
uriFreeUriMembersA(&uri_data);
free(filename);
exit(0);
}
The documentation indicates 6
is the correct offset, but I tried the 4
because file:
is 5 characters long, so subtract 1 to give space for the final NULL
byte.
I'm not sure if this is me misusing the library or a bug in the library, but I would appreciate any insight.
Edited to add: It's also not consistent across test_uri
lengths. For example, if I add 90
to the end of test_uri
const char* test_uri = "file:/01234567890123456789012345678901234567890";
the first example works. But if I only add 9
it fails.
Hi @b-carr I'm currently recovering from the second vaccine, I'll have a closer look soon-ish.
Hi @b-carr I have some updates:
- First, I should mention that adding
uriUriStringToUnixFilename
to the library for convenience was a bad idea. It does not do the proper URI spec parsing thaturiParseSingleUri
does, but some basic detection and copying strings around. - (For the record, a Unix file URL needed three slashes, e.g.
file:///etc/passwd
rather thanfile:/etc/passwd
, at least until RFC8089 of 2017). - The "invalid pointer" is hit inside
uriFreeUriMembers
when freeing path segment "012[..]890" using plainfree
, at least over here, but it happens only some of the time. Cool! 😉 - The path segment was allocated with
calloc
and is trying to be freed byfree
, with the original call return value and no realloc happening in between. So that's something that "should not fail" and indicates "things being very off". - With your original input
"file:/012[..]678"
and lengthstrlen(test_uri)-6
, memcpy copies into post allocation space and my guess is that that cause memory corruption. - I found commit 6d9f2cf and pull request #14 that introduced the current handling with release 0.8.6
- … and there is no update the to the related space requirements documentation
- … or anywhere after, it seems.
So to summarize, I think:
- You used uriparser correctly, with regards to the documentation.
- And found a bug in the documentation — cool, thanks for the report! 🙏
- And the documentation needs to be patched to say
len(uriString) + 1 - 5
for the de-facto worst case.
What do you think?
Works for me, thanks!