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

Errors when initialising a struct with partial keywords or arguments #102

Open
yunzheng opened this issue Sep 26, 2024 · 5 comments
Open
Labels
bug Something isn't working

Comments

@yunzheng
Copy link
Member

yunzheng commented Sep 26, 2024

When initialising a struct with partial keywords or arguments the other fields become None resulting in exceptions, for example when printing the instance of the struct.

When initialising without any arguments it works and all values are 0 as expected. But when you only initialise some of the fields it breaks, example:

from dissect.cstruct import cstruct

C_DEF = """"
struct FooBar {
    uint32  foo;
    uint32  bar;
};
"""

cs = cstruct().load(C_DEF)

print(cs.FooBar())  # works as expected: <FooBar foo=0x0 bar=0x0>
print(cs.FooBar(1, 1)) # works as expected: <FooBar foo=0x1 bar=0x1>

print(cs.FooBar(1)) # breaks, bar=None
print(cs.FooBar(bar=1)) # breaks, foo=None

The exception:

$ python3 kwargs_init.py 
<FooBar foo=0x0 bar=0x0>
<FooBar foo=0x1 bar=0x1>
Traceback (most recent call last):
  File "/workspaces/dissect.cstruct/examples/kwargs_init.py", line 14, in <module>
    print(cs.FooBar(1)) # breaks, bar=None
    ^^^^^^^^^^^^^^^^^^^
  File "/workspaces/dissect.cstruct/dissect/cstruct/types/structure.py", line 388, in __repr__
    value = hex(value)
            ^^^^^^^^^^
TypeError: 'NoneType' object cannot be interpreted as an integer
@yunzheng yunzheng changed the title Errors when initialising a struct with some partial keywords or arguments Errors when initialising a struct with partial keywords or arguments Sep 26, 2024
@Schamper
Copy link
Member

I think it's more the repr that breaks, not the initialization, right? I think this is actually a bug introduced with #101 😄

@Schamper Schamper added the bug Something isn't working label Sep 26, 2024
@yunzheng
Copy link
Member Author

But if you don't initialise with any arguments it works. So it's more the initialisation behaviour i think.

@yunzheng
Copy link
Member Author

yunzheng commented Sep 26, 2024

The bug also happens before merging #101, in the 4.1 tagged release:

$ python3 kwargs_init.py 
<FooBar foo=0x0 bar=0x0>
<FooBar foo=0x1 bar=0x1>
Traceback (most recent call last):
  File "/workspaces/dissect.cstruct/examples/kwargs_init.py", line 14, in <module>
    print(cs.FooBar(1)) # breaks, bar=None
    ^^^^^^^^^^^^^^^^^^^
  File "/workspaces/dissect.cstruct/dissect/cstruct/types/structure.py", line 384, in __repr__
    f"{k}={hex(self[k]) if (issubclass(f.type, int) and not issubclass(f.type, Pointer)) else repr(self[k])}"
           ^^^^^^^^^^^^
TypeError: 'NoneType' object cannot be interpreted as an integer

To be clear in the example, the following works:

print(cs.FooBar())
print(cs.FooBar(foo=1, bar=2))

The following breaks, only one field initialised from the two fields:

print(cs.FooBar(foo=1))

@Schamper
Copy link
Member

Schamper commented Sep 26, 2024

We looked at the code together and decided it’s best to change the default initialization behavior of None to be the default for that type instead.

@yunzheng
Copy link
Member Author

I've currently used the following workaround, which is to initialise it empty first without any arguments, then set the partial values via attributes afterwards, eg:

>>> c = cs.FooBar()
>>> c.foo = 0x1337
>>> print(c)
<FooBar foo=0x1337 bar=0x0>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants