* Symbols with templates are completely ignored for now (ie. they won't confuse
the demangler anymore). * Functions with leading "__" won't confuse the demangler anymore either. * Added a maximum argument count of 32 to reduce the risk of endless loops. * Added protection against recursively calling get_next_argument_internal() more than once. * Added detection for floats, and doubles (long doubles will currently make it reject the symbol). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28032 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -39,6 +39,10 @@ argument_type(const char* arg, size_t& length)
|
|||||||
ignore_qualifiers(&arg);
|
ignore_qualifiers(&arg);
|
||||||
if (arg[0] == 'c')
|
if (arg[0] == 'c')
|
||||||
return B_STRING_TYPE;
|
return B_STRING_TYPE;
|
||||||
|
if (arg[0] == 't') {
|
||||||
|
// TODO: templates are not yet supported
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return type == 'P' ? B_POINTER_TYPE : B_REF_TYPE;
|
return type == 'P' ? B_POINTER_TYPE : B_REF_TYPE;
|
||||||
case 'x':
|
case 'x':
|
||||||
@@ -76,6 +80,19 @@ argument_type(const char* arg, size_t& length)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
return B_FLOAT_TYPE;
|
||||||
|
case 'd':
|
||||||
|
length = sizeof(double);
|
||||||
|
return B_DOUBLE_TYPE;
|
||||||
|
case 'r':
|
||||||
|
// TODO: is "long double" supported under Haiku at all?
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
// TODO: templates are not yet supported
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return B_ANY_TYPE;
|
return B_ANY_TYPE;
|
||||||
}
|
}
|
||||||
@@ -235,25 +252,119 @@ mangled_start(const char* name, size_t* _symbolLength, int32* _symbolType)
|
|||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
const char* mangled = strstr(name, "__");
|
// search '__' starting from the end, don't accept them at the start
|
||||||
|
size_t pos = strlen(name) - 1;
|
||||||
|
const char* mangled = NULL;
|
||||||
|
|
||||||
|
while (pos > 1) {
|
||||||
|
if (name[pos] == '_') {
|
||||||
|
if (name[pos - 1] == '_') {
|
||||||
|
mangled = name + pos + 1;
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
|
||||||
if (mangled == NULL)
|
if (mangled == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (_symbolLength != NULL)
|
if (mangled[0] == 'H') {
|
||||||
*_symbolLength = mangled - name;
|
// TODO: we don't support templates yet
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (mangled[2] == 'F') {
|
if (_symbolLength != NULL)
|
||||||
|
*_symbolLength = pos - 1;
|
||||||
|
|
||||||
|
if (mangled[0] == 'F') {
|
||||||
if (_symbolType != NULL)
|
if (_symbolType != NULL)
|
||||||
*_symbolType = TYPE_FUNCTION;
|
*_symbolType = TYPE_FUNCTION;
|
||||||
return mangled + 3;
|
return mangled + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_symbolType != NULL)
|
if (_symbolType != NULL)
|
||||||
*_symbolType = TYPE_METHOD;
|
*_symbolType = TYPE_METHOD;
|
||||||
return mangled + 2;
|
return mangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
get_next_argument_internal(uint32* _cookie, const char* symbol, char* name,
|
||||||
|
size_t nameSize, int32* _type, size_t* _argumentLength, bool repeating)
|
||||||
|
{
|
||||||
|
const char* mangled = mangled_start(symbol, NULL, NULL);
|
||||||
|
if (mangled == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
const char* arg = first_argument(mangled);
|
||||||
|
|
||||||
|
// (void) is not an argument
|
||||||
|
if (arg != NULL && arg[0] == 'v')
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
uint32 current = *_cookie;
|
||||||
|
if (current > 32)
|
||||||
|
return B_TOO_MANY_ARGS;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < current; i++) {
|
||||||
|
arg = next_argument(arg);
|
||||||
|
if (arg != NULL && arg[0] == 'N') {
|
||||||
|
// repeat argument 'count' times
|
||||||
|
uint32 index;
|
||||||
|
uint32 count = parse_repeats(&arg, index);
|
||||||
|
if (current <= i + count) {
|
||||||
|
if (repeating)
|
||||||
|
return B_LINK_LIMIT;
|
||||||
|
|
||||||
|
// it's a repeat case
|
||||||
|
status_t status = get_next_argument_internal(&index, symbol, name,
|
||||||
|
nameSize, _type, _argumentLength, true);
|
||||||
|
if (status == B_OK)
|
||||||
|
(*_cookie)++;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += count - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
if (arg[0] == 'T') {
|
||||||
|
// duplicate argument
|
||||||
|
if (repeating)
|
||||||
|
return B_LINK_LIMIT;
|
||||||
|
|
||||||
|
arg++;
|
||||||
|
uint32 index = parse_number(&arg, false);
|
||||||
|
status_t status = get_next_argument_internal(&index, symbol, name,
|
||||||
|
nameSize, _type, _argumentLength, true);
|
||||||
|
if (status == B_OK)
|
||||||
|
(*_cookie)++;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*_cookie)++;
|
||||||
|
|
||||||
|
size_t argumentLength;
|
||||||
|
int32 type = argument_type(arg, argumentLength);
|
||||||
|
if (type == 0)
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (_type != NULL)
|
||||||
|
*_type = type;
|
||||||
|
if (_argumentLength != NULL)
|
||||||
|
*_argumentLength = argumentLength;
|
||||||
|
|
||||||
|
uint32 length = argument_name_length(&arg);
|
||||||
|
strlcpy(name, arg, min_c(length + 1, nameSize));
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
@@ -299,63 +410,8 @@ status_t
|
|||||||
get_next_argument(uint32* _cookie, const char* symbol, char* name,
|
get_next_argument(uint32* _cookie, const char* symbol, char* name,
|
||||||
size_t nameSize, int32* _type, size_t* _argumentLength)
|
size_t nameSize, int32* _type, size_t* _argumentLength)
|
||||||
{
|
{
|
||||||
const char* mangled = mangled_start(symbol, NULL, NULL);
|
return get_next_argument_internal(_cookie, symbol, name, nameSize, _type,
|
||||||
if (mangled == NULL)
|
_argumentLength, false);
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
const char* arg = first_argument(mangled);
|
|
||||||
|
|
||||||
// (void) is not an argument
|
|
||||||
if (arg != NULL && arg[0] == 'v')
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
|
|
||||||
uint32 current = *_cookie;
|
|
||||||
for (uint32 i = 0; i < current; i++) {
|
|
||||||
arg = next_argument(arg);
|
|
||||||
if (arg != NULL && arg[0] == 'N') {
|
|
||||||
// repeat argument 'count' times
|
|
||||||
uint32 index;
|
|
||||||
uint32 count = parse_repeats(&arg, index);
|
|
||||||
if (current <= i + count) {
|
|
||||||
// it's a repeat case
|
|
||||||
status_t status = get_next_argument(&index, symbol, name,
|
|
||||||
nameSize, _type, _argumentLength);
|
|
||||||
if (status == B_OK)
|
|
||||||
(*_cookie)++;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
i += count - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg == NULL)
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
|
|
||||||
if (arg[0] == 'T') {
|
|
||||||
// duplicate argument
|
|
||||||
arg++;
|
|
||||||
uint32 index = parse_number(&arg, false);
|
|
||||||
status_t status = get_next_argument(&index, symbol, name,
|
|
||||||
nameSize, _type, _argumentLength);
|
|
||||||
if (status == B_OK)
|
|
||||||
(*_cookie)++;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*_cookie)++;
|
|
||||||
|
|
||||||
size_t argumentLength;
|
|
||||||
int32 type = argument_type(arg, argumentLength);
|
|
||||||
if (_type != NULL)
|
|
||||||
*_type = type;
|
|
||||||
if (_argumentLength != NULL)
|
|
||||||
*_argumentLength = argumentLength;
|
|
||||||
|
|
||||||
uint32 length = argument_name_length(&arg);
|
|
||||||
strlcpy(name, arg, min_c(length + 1, nameSize));
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user