Index: lib/sanitizer_common/sanitizer_symbolizer.h =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer.h +++ lib/sanitizer_common/sanitizer_symbolizer.h @@ -24,6 +24,15 @@ namespace __sanitizer { +// Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr +// is extracted. When extracting a string, a newly allocated (using +// InternalAlloc) and null-terminataed buffer is returned. They return a pointer +// to the next characted after the found delimiter. +const char *ExtractToken(const char *str, const char *delims, char **result); +const char *ExtractUptr(const char *str, const char *delims, uptr *result); +const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter, + char **result); + struct AddressInfo { // Owns all the string members. Storage for them is // (de)allocated using sanitizer internal allocator. Index: lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -60,8 +60,7 @@ // space for it. // Returns a pointer to "str" after skipping extracted prefix and first // delimiter char. -static const char *ExtractToken(const char *str, const char *delims, - char **result) { +const char *ExtractToken(const char *str, const char *delims, char **result) { uptr prefix_len = internal_strcspn(str, delims); *result = (char*)InternalAlloc(prefix_len + 1); internal_memcpy(*result, str, prefix_len); @@ -71,27 +70,30 @@ return prefix_end; } -// Same as ExtractToken, but converts extracted token to integer. -static const char *ExtractInt(const char *str, const char *delims, - int *result) { +// Same as ExtractToken, but converts extracted token to uptr. +const char *ExtractUptr(const char *str, const char *delims, uptr *result) { char *buff; const char *ret = ExtractToken(str, delims, &buff); if (buff != 0) { - *result = (int)internal_atoll(buff); + *result = (uptr)internal_atoll(buff); } InternalFree(buff); return ret; } -static const char *ExtractUptr(const char *str, const char *delims, - uptr *result) { - char *buff; - const char *ret = ExtractToken(str, delims, &buff); - if (buff != 0) { - *result = (uptr)internal_atoll(buff); - } - InternalFree(buff); - return ret; +// Similar to ExtractToken, but looks only for a single delimiter which can +// be multiple characters long. +const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter, + char **result) { + const char *found_delimiter = internal_strstr(str, delimiter); + uptr prefix_len = + found_delimiter ? found_delimiter - str : internal_strlen(str); + *result = (char *)InternalAlloc(prefix_len + 1); + internal_memcpy(*result, str, prefix_len); + (*result)[prefix_len] = '\0'; + const char *prefix_end = str + prefix_len; + if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter); + return prefix_end; } class ExternalSymbolizerInterface { @@ -565,8 +567,14 @@ str = ExtractToken(str, "\n", &file_line_info); CHECK(file_line_info); const char *line_info = ExtractToken(file_line_info, ":", &info->file); - line_info = ExtractInt(line_info, ":", &info->line); - line_info = ExtractInt(line_info, "", &info->column); + uptr line_number; + line_info = ExtractUptr(line_info, ":", &line_number); + info->line = line_number; + if (*line_info != '\0') { + uptr column_number; + line_info = ExtractUptr(line_info, "", &column_number); + info->column = column_number; + } InternalFree(file_line_info); // Functions and filenames can be "??", in which case we write 0