mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-23 07:05:58 +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 =
|
||||
Pattern.compile(
|
||||
"\\s(?:const[\\[\\]\\d\\*&]{0,4}\\s)*\\(([&*])\\)\\s*((?:\\[.*?\\])+)");
|
||||
Pattern.compile("\\s(?:const[\\[\\]\\d\\*&]{0,4}\\s)*\\(([&*])\\)\\s*((?:\\[.*?\\])+)");
|
||||
|
||||
/*
|
||||
* Sample: bob(short (&)[7])
|
||||
@@ -836,16 +835,15 @@ public class GnuDemanglerParser {
|
||||
if (hasPointerParens) {
|
||||
Demangled namespace = dt.getNamespace();
|
||||
DemangledFunctionPointer dfp = parseFunctionPointer(datatype);
|
||||
int firstParenEnd = datatype.indexOf(')', i + 1);
|
||||
int secondParenEnd = datatype.indexOf(')', firstParenEnd + 1);
|
||||
if (secondParenEnd == -1) {
|
||||
int paramParenEnd = datatype.lastIndexOf(')');
|
||||
if (paramParenEnd == -1) {
|
||||
throw new DemanglerParseException(
|
||||
"Did not find ending to closure: " + datatype);
|
||||
}
|
||||
|
||||
dfp.getReturnType().setNamespace(namespace);
|
||||
dt = dfp;
|
||||
i = secondParenEnd + 1; // two sets of parens (normal case)
|
||||
i = paramParenEnd + 1; // two sets of parens (normal case)
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -970,8 +968,8 @@ public class GnuDemanglerParser {
|
||||
|
||||
Demangled namespace = dt.getNamespace();
|
||||
String name = leading;
|
||||
DemangledDataType newDt = parseArrayPointerOrReference(datatype, name, lambdaString,
|
||||
matcher);
|
||||
DemangledDataType newDt =
|
||||
parseArrayPointerOrReference(datatype, name, lambdaString, matcher);
|
||||
newDt.setNamespace(namespace);
|
||||
return newDt;
|
||||
}
|
||||
@@ -993,8 +991,8 @@ public class GnuDemanglerParser {
|
||||
|
||||
Demangled namespace = dt.getNamespace();
|
||||
String name = leading;
|
||||
DemangledDataType newDt = parseArrayPointerOrReference(datatype, name, templatedString,
|
||||
matcher);
|
||||
DemangledDataType newDt =
|
||||
parseArrayPointerOrReference(datatype, name, templatedString, matcher);
|
||||
newDt.setNamespace(namespace);
|
||||
return newDt;
|
||||
}
|
||||
@@ -1052,9 +1050,9 @@ public class GnuDemanglerParser {
|
||||
/*
|
||||
Note: really, this should just be checking a list of known disallowed characters,
|
||||
which is something like:
|
||||
|
||||
|
||||
<,>,(,),&,*,[,]
|
||||
|
||||
|
||||
It seems like the current code below is unnecessarily restrictive
|
||||
*/
|
||||
|
||||
@@ -1369,9 +1367,9 @@ public class GnuDemanglerParser {
|
||||
|
||||
/*
|
||||
Examples:
|
||||
|
||||
|
||||
NS1::Function<>()::StructureName::StructureConstructor()
|
||||
|
||||
|
||||
*/
|
||||
|
||||
String nameString = removeBadSpaces(demangled).trim();
|
||||
@@ -1553,13 +1551,13 @@ public class GnuDemanglerParser {
|
||||
Samples:
|
||||
prefix: construction vtable for
|
||||
name: construction-vtable
|
||||
|
||||
|
||||
prefix: vtable for
|
||||
name: vtable
|
||||
|
||||
|
||||
prefix: typeinfo name for
|
||||
name: typeinfo-name
|
||||
|
||||
|
||||
prefix: covariant return thunk
|
||||
name: covariant-return
|
||||
*/
|
||||
|
||||
+26
-38
@@ -387,8 +387,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
//
|
||||
// The demangled string contains this string: {unnamed_type#1}
|
||||
//
|
||||
String mangled =
|
||||
"_ZN14GoalDefinitionUt_aSERKS0_";
|
||||
String mangled = "_ZN14GoalDefinitionUt_aSERKS0_";
|
||||
|
||||
String demangled = process.demangle(mangled);
|
||||
|
||||
@@ -397,16 +396,14 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertType(object, DemangledFunction.class);
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"undefined GoalDefinition::{unnamed_type#1}::operator=({unnamed const &)",
|
||||
assertEquals("undefined GoalDefinition::{unnamed_type#1}::operator=({unnamed const &)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParse_DecltypeAuto() throws Exception {
|
||||
|
||||
String mangled =
|
||||
"_Z9enum_castIN17FurnaceBlockActorUt_EEDcT_";
|
||||
String mangled = "_Z9enum_castIN17FurnaceBlockActorUt_EEDcT_";
|
||||
|
||||
String demangled = process.demangle(mangled);
|
||||
|
||||
@@ -1034,9 +1031,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
std::__ndk1::allocator<{lambda(dummy::it::other::Namespace*)#1}>,
|
||||
int (dummy::it::other::Namespace*)
|
||||
>
|
||||
|
||||
|
||||
'__func' has 3 template parameters, the operator and the allocator
|
||||
|
||||
|
||||
*/
|
||||
|
||||
String dummyNs = "dummy::it::other::Namespace";
|
||||
@@ -1103,13 +1100,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
public void testOperator_WithTemplatesMissingATemplateArgument() throws Exception {
|
||||
|
||||
/*
|
||||
|
||||
|
||||
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::_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 =
|
||||
"_ZNSt5_BindIFM13EduAppConfigsKFNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvEPKS0_EEclIJES6_EET0_DpOT_";
|
||||
@@ -1163,9 +1160,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
public void testLambdaWithLambdaParameters() throws Exception {
|
||||
|
||||
/*
|
||||
|
||||
|
||||
lambda contents - lambdas in templates and as a parameter
|
||||
|
||||
|
||||
bool (***
|
||||
const* std::
|
||||
__addressof<
|
||||
@@ -1185,7 +1182,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
{lambda(bool (*** const&)(AssertHandlerContext const&))#1}
|
||||
)
|
||||
)(AssertHandlerContext const&)
|
||||
|
||||
|
||||
*/
|
||||
|
||||
String mangled =
|
||||
@@ -1230,25 +1227,25 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
String demangled = process.demangle(mangled);
|
||||
|
||||
/*
|
||||
|
||||
|
||||
Full demangled:
|
||||
|
||||
|
||||
Operator Text
|
||||
|
||||
|
||||
entt::
|
||||
basic_registry<EntityId>::
|
||||
assure<FilteredTransformationAttributes<PreHillsEdgeTransformation> >() const::
|
||||
{lambda(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)#1}::
|
||||
operator void (*)(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)() const
|
||||
|
||||
|
||||
Operartor Without Namespace
|
||||
|
||||
|
||||
operator void (*)(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)()
|
||||
|
||||
|
||||
Simplified Cast Operator Construct
|
||||
|
||||
|
||||
operator void (*)(A,B,C)()
|
||||
|
||||
|
||||
*/
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
@@ -1872,20 +1869,20 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
|
||||
Demangled:
|
||||
|
||||
|
||||
auto && JsonUtil::
|
||||
addMember<std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,AvoidBlockGoal::Definition,float>
|
||||
(
|
||||
|
||||
|
||||
std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,
|
||||
float AvoidBlockGoal::Definition::*,
|
||||
char const *,
|
||||
float AvoidBlockGoal::Definition::* const&
|
||||
|
||||
|
||||
)
|
||||
|
||||
|
||||
*/
|
||||
String mangled =
|
||||
"_ZN8JsonUtil9addMemberISt10shared_ptrINS_20JsonSchemaObjectNodeINS_10EmptyClassEN14AvoidBlockGoal10DefinitionEEEES5_fEEODaT_MT0_T1_PKcRKSC_";
|
||||
@@ -1928,17 +1925,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
|
||||
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(
|
||||
"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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user