mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-31 19:28:34 +08:00
GP-3650 - Fixed GNU demangler parsing bug
This commit is contained in:
+15
-17
@@ -118,8 +118,7 @@ public class GnuDemanglerParser {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final Pattern ARRAY_POINTER_REFERENCE_PATTERN =
|
private static final Pattern ARRAY_POINTER_REFERENCE_PATTERN =
|
||||||
Pattern.compile(
|
Pattern.compile("\\s(?:const[\\[\\]\\d\\*&]{0,4}\\s)*\\(([&*])\\)\\s*((?:\\[.*?\\])+)");
|
||||||
"\\s(?:const[\\[\\]\\d\\*&]{0,4}\\s)*\\(([&*])\\)\\s*((?:\\[.*?\\])+)");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sample: bob(short (&)[7])
|
* Sample: bob(short (&)[7])
|
||||||
@@ -836,16 +835,15 @@ public class GnuDemanglerParser {
|
|||||||
if (hasPointerParens) {
|
if (hasPointerParens) {
|
||||||
Demangled namespace = dt.getNamespace();
|
Demangled namespace = dt.getNamespace();
|
||||||
DemangledFunctionPointer dfp = parseFunctionPointer(datatype);
|
DemangledFunctionPointer dfp = parseFunctionPointer(datatype);
|
||||||
int firstParenEnd = datatype.indexOf(')', i + 1);
|
int paramParenEnd = datatype.lastIndexOf(')');
|
||||||
int secondParenEnd = datatype.indexOf(')', firstParenEnd + 1);
|
if (paramParenEnd == -1) {
|
||||||
if (secondParenEnd == -1) {
|
|
||||||
throw new DemanglerParseException(
|
throw new DemanglerParseException(
|
||||||
"Did not find ending to closure: " + datatype);
|
"Did not find ending to closure: " + datatype);
|
||||||
}
|
}
|
||||||
|
|
||||||
dfp.getReturnType().setNamespace(namespace);
|
dfp.getReturnType().setNamespace(namespace);
|
||||||
dt = dfp;
|
dt = dfp;
|
||||||
i = secondParenEnd + 1; // two sets of parens (normal case)
|
i = paramParenEnd + 1; // two sets of parens (normal case)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
@@ -970,8 +968,8 @@ public class GnuDemanglerParser {
|
|||||||
|
|
||||||
Demangled namespace = dt.getNamespace();
|
Demangled namespace = dt.getNamespace();
|
||||||
String name = leading;
|
String name = leading;
|
||||||
DemangledDataType newDt = parseArrayPointerOrReference(datatype, name, lambdaString,
|
DemangledDataType newDt =
|
||||||
matcher);
|
parseArrayPointerOrReference(datatype, name, lambdaString, matcher);
|
||||||
newDt.setNamespace(namespace);
|
newDt.setNamespace(namespace);
|
||||||
return newDt;
|
return newDt;
|
||||||
}
|
}
|
||||||
@@ -993,8 +991,8 @@ public class GnuDemanglerParser {
|
|||||||
|
|
||||||
Demangled namespace = dt.getNamespace();
|
Demangled namespace = dt.getNamespace();
|
||||||
String name = leading;
|
String name = leading;
|
||||||
DemangledDataType newDt = parseArrayPointerOrReference(datatype, name, templatedString,
|
DemangledDataType newDt =
|
||||||
matcher);
|
parseArrayPointerOrReference(datatype, name, templatedString, matcher);
|
||||||
newDt.setNamespace(namespace);
|
newDt.setNamespace(namespace);
|
||||||
return newDt;
|
return newDt;
|
||||||
}
|
}
|
||||||
@@ -1052,9 +1050,9 @@ public class GnuDemanglerParser {
|
|||||||
/*
|
/*
|
||||||
Note: really, this should just be checking a list of known disallowed characters,
|
Note: really, this should just be checking a list of known disallowed characters,
|
||||||
which is something like:
|
which is something like:
|
||||||
|
|
||||||
<,>,(,),&,*,[,]
|
<,>,(,),&,*,[,]
|
||||||
|
|
||||||
It seems like the current code below is unnecessarily restrictive
|
It seems like the current code below is unnecessarily restrictive
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1369,9 +1367,9 @@ public class GnuDemanglerParser {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
NS1::Function<>()::StructureName::StructureConstructor()
|
NS1::Function<>()::StructureName::StructureConstructor()
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String nameString = removeBadSpaces(demangled).trim();
|
String nameString = removeBadSpaces(demangled).trim();
|
||||||
@@ -1553,13 +1551,13 @@ public class GnuDemanglerParser {
|
|||||||
Samples:
|
Samples:
|
||||||
prefix: construction vtable for
|
prefix: construction vtable for
|
||||||
name: construction-vtable
|
name: construction-vtable
|
||||||
|
|
||||||
prefix: vtable for
|
prefix: vtable for
|
||||||
name: vtable
|
name: vtable
|
||||||
|
|
||||||
prefix: typeinfo name for
|
prefix: typeinfo name for
|
||||||
name: typeinfo-name
|
name: typeinfo-name
|
||||||
|
|
||||||
prefix: covariant return thunk
|
prefix: covariant return thunk
|
||||||
name: covariant-return
|
name: covariant-return
|
||||||
*/
|
*/
|
||||||
|
|||||||
+26
-38
@@ -387,8 +387,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
//
|
//
|
||||||
// The demangled string contains this string: {unnamed_type#1}
|
// The demangled string contains this string: {unnamed_type#1}
|
||||||
//
|
//
|
||||||
String mangled =
|
String mangled = "_ZN14GoalDefinitionUt_aSERKS0_";
|
||||||
"_ZN14GoalDefinitionUt_aSERKS0_";
|
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
@@ -397,16 +396,14 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
assertType(object, DemangledFunction.class);
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
assertEquals(
|
assertEquals("undefined GoalDefinition::{unnamed_type#1}::operator=({unnamed const &)",
|
||||||
"undefined GoalDefinition::{unnamed_type#1}::operator=({unnamed const &)",
|
|
||||||
signature);
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParse_DecltypeAuto() throws Exception {
|
public void testParse_DecltypeAuto() throws Exception {
|
||||||
|
|
||||||
String mangled =
|
String mangled = "_Z9enum_castIN17FurnaceBlockActorUt_EEDcT_";
|
||||||
"_Z9enum_castIN17FurnaceBlockActorUt_EEDcT_";
|
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
@@ -1034,9 +1031,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
std::__ndk1::allocator<{lambda(dummy::it::other::Namespace*)#1}>,
|
std::__ndk1::allocator<{lambda(dummy::it::other::Namespace*)#1}>,
|
||||||
int (dummy::it::other::Namespace*)
|
int (dummy::it::other::Namespace*)
|
||||||
>
|
>
|
||||||
|
|
||||||
'__func' has 3 template parameters, the operator and the allocator
|
'__func' has 3 template parameters, the operator and the allocator
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String dummyNs = "dummy::it::other::Namespace";
|
String dummyNs = "dummy::it::other::Namespace";
|
||||||
@@ -1103,13 +1100,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
public void testOperator_WithTemplatesMissingATemplateArgument() throws Exception {
|
public void testOperator_WithTemplatesMissingATemplateArgument() throws Exception {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Note: the empty template type: '<, std...'
|
Note: the empty template type: '<, std...'
|
||||||
<, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>
|
<, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>
|
||||||
|
|
||||||
|
|
||||||
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::_Bind<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (EduAppConfigs::*(EduAppConfigs const*))() const>::operator()<, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >()
|
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::_Bind<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (EduAppConfigs::*(EduAppConfigs const*))() const>::operator()<, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >()
|
||||||
|
|
||||||
*/
|
*/
|
||||||
String mangled =
|
String mangled =
|
||||||
"_ZNSt5_BindIFM13EduAppConfigsKFNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvEPKS0_EEclIJES6_EET0_DpOT_";
|
"_ZNSt5_BindIFM13EduAppConfigsKFNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvEPKS0_EEclIJES6_EET0_DpOT_";
|
||||||
@@ -1163,9 +1160,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
public void testLambdaWithLambdaParameters() throws Exception {
|
public void testLambdaWithLambdaParameters() throws Exception {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
lambda contents - lambdas in templates and as a parameter
|
lambda contents - lambdas in templates and as a parameter
|
||||||
|
|
||||||
bool (***
|
bool (***
|
||||||
const* std::
|
const* std::
|
||||||
__addressof<
|
__addressof<
|
||||||
@@ -1185,7 +1182,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
{lambda(bool (*** const&)(AssertHandlerContext const&))#1}
|
{lambda(bool (*** const&)(AssertHandlerContext const&))#1}
|
||||||
)
|
)
|
||||||
)(AssertHandlerContext const&)
|
)(AssertHandlerContext const&)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String mangled =
|
String mangled =
|
||||||
@@ -1230,25 +1227,25 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Full demangled:
|
Full demangled:
|
||||||
|
|
||||||
Operator Text
|
Operator Text
|
||||||
|
|
||||||
entt::
|
entt::
|
||||||
basic_registry<EntityId>::
|
basic_registry<EntityId>::
|
||||||
assure<FilteredTransformationAttributes<PreHillsEdgeTransformation> >() const::
|
assure<FilteredTransformationAttributes<PreHillsEdgeTransformation> >() const::
|
||||||
{lambda(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)#1}::
|
{lambda(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)#1}::
|
||||||
operator void (*)(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)() const
|
operator void (*)(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)() const
|
||||||
|
|
||||||
Operartor Without Namespace
|
Operartor Without Namespace
|
||||||
|
|
||||||
operator void (*)(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)()
|
operator void (*)(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)()
|
||||||
|
|
||||||
Simplified Cast Operator Construct
|
Simplified Cast Operator Construct
|
||||||
|
|
||||||
operator void (*)(A,B,C)()
|
operator void (*)(A,B,C)()
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DemangledObject object = parser.parse(mangled, demangled);
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
@@ -1872,20 +1869,20 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
//
|
//
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Demangled:
|
Demangled:
|
||||||
|
|
||||||
auto && JsonUtil::
|
auto && JsonUtil::
|
||||||
addMember<std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,AvoidBlockGoal::Definition,float>
|
addMember<std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,AvoidBlockGoal::Definition,float>
|
||||||
(
|
(
|
||||||
|
|
||||||
std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,
|
std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,
|
||||||
float AvoidBlockGoal::Definition::*,
|
float AvoidBlockGoal::Definition::*,
|
||||||
char const *,
|
char const *,
|
||||||
float AvoidBlockGoal::Definition::* const&
|
float AvoidBlockGoal::Definition::* const&
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
String mangled =
|
String mangled =
|
||||||
"_ZN8JsonUtil9addMemberISt10shared_ptrINS_20JsonSchemaObjectNodeINS_10EmptyClassEN14AvoidBlockGoal10DefinitionEEEES5_fEEODaT_MT0_T1_PKcRKSC_";
|
"_ZN8JsonUtil9addMemberISt10shared_ptrINS_20JsonSchemaObjectNodeINS_10EmptyClassEN14AvoidBlockGoal10DefinitionEEEES5_fEEODaT_MT0_T1_PKcRKSC_";
|
||||||
@@ -1928,17 +1925,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
|
|
||||||
// 20230719: Note that argument in the following function is not correctly parsed.
|
|
||||||
// The argument is a non-pointer/ref reference to a function that returns void and
|
|
||||||
// which takes the argument list shown. Parser looks for double closing parenthesis,
|
|
||||||
// but that is found on the last argument of the template parameter. It actually needed
|
|
||||||
// to find the last closing parethesis and know that there could be nested pairs.
|
|
||||||
// Modification on 20230719 has "(* &&)" emitted in place of "(*)" because of lref/rref
|
|
||||||
// work in GP-3649, but the "&&" was found due to the closing parenthesis issue, which
|
|
||||||
// already existed.
|
|
||||||
// TODO: needs fixed
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"undefined WebCore::TextCodecICU::registerCodecs(void (* &&)(char const *,WTF::Function<std::__1::unique_ptr<WebCore::TextCodec,std::__1::default_delete<WebCore::TextCodec>> ()> &&))",
|
"undefined WebCore::TextCodecICU::registerCodecs(void (*)(char const *,WTF::Function<std::__1::unique_ptr<WebCore::TextCodec,std::__1::default_delete<WebCore::TextCodec>> ()> &&))",
|
||||||
signature);
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user