uriparser / uriparser

:hocho: Strictly RFC 3986 compliant URI parsing and handling library written in C89; moved from SourceForge to GitHub

Home Page:https://uriparser.github.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

```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 that uriParseSingleUri 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 than file:/etc/passwd, at least until RFC8089 of 2017).
  • The "invalid pointer" is hit inside uriFreeUriMembers when freeing path segment "012[..]890" using plain free, 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 by free, 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 length strlen(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!