uriparser / uriparser

:hocho: Strictly RFC 3986 compliant URI parsing and handling library written in C89; moved from SourceForge to GitHub
https://uriparser.github.io/
Other
336 stars 79 forks source link

```free(): Invalid pointer``` when using ```uriParseSingleUriA``` and ```uriUriStringToUnixFilenameA``` #118

Closed b-carr closed 3 years ago

b-carr commented 3 years ago

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.

hartwork commented 3 years ago

Hi @b-carr I'm currently recovering from the second vaccine, I'll have a closer look soon-ish.

hartwork commented 3 years ago

Hi @b-carr I have some updates:

So to summarize, I think:

What do you think?

b-carr commented 3 years ago

Works for me, thanks!