-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix decompiler display of char array #3001
fix decompiler display of char array #3001
Conversation
if (data.getDataType() instanceof AbstractStringDataType) { | ||
// There is already a string here. Use its configuration to | ||
// set up the StringDataInstance | ||
if (data.getDataType() instanceof AbstractStringDataType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (data.getDataType() instanceof AbstractStringDataType | |
if (data.hasStringValue()) |
I believe this method is more appropriate here.
ps I'm on my phone so line selections may be wierd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it is more appropriate. But for now I can not be 100% sure if data.hasStringValue()
returns true, the only possible data types are AbstractStringDataType
and Array
.
And later, the getStringDataInstance
method are not abstracted out of DataType
, i.e, there's no interface contains such a method.
Thus, current implementation checks the type with instanceof
one by one (this it the implementation before this patch anyway).
If we use hasStringValue()
here, I suppose we have two options:
- figure out what are the potential types and type check and cast them one by one then call
getStringDataInstance
method. - do some more abstraction, use interface like
StringableDataType
and contains method ofgetStringDataInstance
.
And for now, I'm not confident enough I can do either without any help. (I'm also working on some more fixings related to better Rust decompilation. I tend to make them work first)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try the following. It appears that the work is already done in StringDataInstance.
You can actually skip the entire if (data == null)
block and instead do the following:
StringDataInstance stringInstance = StringDataInstance.getStringDataInstance(data);
if (stringInstance == StringDataInstance.NULL_INSTANCE) {
// previous if (data != null) else block contents L1348-L1377
}
As a side note, when you have a Data
instance and Data.hasStringValue()
returns true
you can do the following:
public static String getStringFromData(Data data) {
if (data.hasStringValue()) {
return (String) data.getValue();
}
return "";
}
With that said, if you want to keep it the way it is because it introduces the smallest amount of changes I think that is fine. I will probably comb through this file to simplify the logic here and check if there are other simplifications that could be made this weekend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the advice! I have pushed the new code adopting that option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm terribly sorry. I made a mistake. Removing the if (data != null)
block completely breaks what the patch was intended to fix. It should go back to how that was. However, it couble be skipped if data.getAddress().equals(addr)
, but I no longer trust myself looking at this with tired eyes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! I just noticed it! I will make it back. You are right, current patch introduces incorrect starting address problem
@@ -1336,13 +1335,20 @@ public StringData getStringData(String addrString, String dtName, String dtId) { | |||
} | |||
length -= diff; | |||
MemoryBufferImpl buf = new MemoryBufferImpl(program.getMemory(), addr, 64); | |||
stringInstance = dataType.getStringDataInstance(buf, settings, length); | |||
if (data.getDataType() instanceof AbstractStringDataType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just in case, I don't think the comment above applies here. This should be correct.
* @return a String if it is an array of chars; otherwise null. | ||
*/ | ||
public default StringDataInstance getStringDataInstance(MemBuffer buf, Settings settings, int length) { | ||
if (!buf.getMemory().getAllInitializedAddressSet().contains(buf.getAddress())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There might be a more appropriate way to check if the address is initialized memory other than collecting the entire set. You could probably peek at the implementation of getAllInitializedAddressSet
for a hint here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this is copied directly from the getArrayValue
down below. If we need a more appropirate way of do this, I think it maybe better to have another PR do this? Since actually.. I haven't checked and totally understood how this part works, but I think they share the same logic so I copied that here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. There is Address.isLoadedMemoryAddress()
but I don't know if this means it is initialized or not. Any other alternative I can think of is more than one line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these 2 other classes necessary for this fix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry this is the thing missing when I clean up code when the data != null
block has been changed. This should be fine now.
// There is no string and/or something else at the address. | ||
// Setup StringDataInstance based on raw memory | ||
DataType dt = dtmanage.findBaseType(dtName, dtId); | ||
AbstractStringDataType dataType = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This local var (dataType) needs a better name, ie. tmpStringDataType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually is the original name... I just followed the previous version. I thought it was better to keep the commit minimum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
* @return a String if it is an array of chars; otherwise null. | ||
*/ | ||
public default StringDataInstance getStringDataInstance(MemBuffer buf, Settings settings, int length) { | ||
if (!buf.getMemory().getAllInitializedAddressSet().contains(buf.getAddress())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these 2 other classes necessary for this fix?
Fixes issue reported in PR #3001
When a char array is splitted out of a long char array, the decompiler's display does not respect the defined data and display the whole string.
This happens a lot when decompiling Rust.
For example, before this patch:
After this patch:
According to this comment, this issue should be resolved in 9.2. But when I try it, it is still a problem. This should fix it.
Previous PR(#3000 ) contains some commits not belong to this patch. It should all be OK now.