Skip to content
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

Conversation

Escapingbug
Copy link
Contributor

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:

image

After this patch:

image

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.

if (data.getDataType() instanceof AbstractStringDataType) {
// There is already a string here. Use its configuration to
// set up the StringDataInstance
if (data.getDataType() instanceof AbstractStringDataType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.

Copy link
Contributor Author

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:

  1. figure out what are the potential types and type check and cast them one by one then call getStringDataInstance method.
  2. do some more abstraction, use interface like StringableDataType and contains method of getStringDataInstance.

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)

Copy link
Contributor

@astrelsky astrelsky May 4, 2021

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.

Copy link
Contributor Author

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.

Copy link
Contributor

@astrelsky astrelsky May 6, 2021

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.

Copy link
Contributor Author

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) {
Copy link
Contributor

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())) {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Collaborator

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?

Copy link
Contributor Author

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;
Copy link
Collaborator

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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())) {
Copy link
Collaborator

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?

@ryanmkurtz ryanmkurtz added this to the 10.3 milestone Nov 3, 2022
@ryanmkurtz ryanmkurtz added the Reason: Internal effort This will be solved internally label Nov 3, 2022
ryanmkurtz pushed a commit that referenced this pull request Nov 8, 2022
@ryanmkurtz ryanmkurtz closed this in f9406b0 Nov 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants