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

added guard for null 'options' to fix crash (#1163) #1325

Conversation

matthewhegarty
Copy link
Contributor

@matthewhegarty matthewhegarty commented Sep 1, 2021

Problem

If the forbiddenfruit library is installed, then crashes are seen at object instantiation.

The cause is that when forbiddenfruit is installed, calling dir() on a null object returns additional properties. The logic attempts to get these properties from a null options reference, which causes the crash:

'NoneType' object has no attribute 'attrs' 

#1163

Solution

This fix adds a check that options is not None.

Acceptance Criteria

  • Ran tests with forbiddenfruit installed
  • A test which simulates the problem is included.
  • Have tested Admin console manually.

@coveralls
Copy link

coveralls commented Sep 1, 2021

Coverage Status

Coverage remained the same at 98.063% when pulling 7a6ecb7 on matthewhegarty:tests_fail_with_forbiddenfruit_imported_issue_1163 into 89e5240 on django-import-export:main.

@matthewhegarty
Copy link
Contributor Author

@manelclos please could you cast your eye over this change - this would be the last one to go into 2.6.0

Copy link
Contributor

@manelclos manelclos left a comment

Choose a reason for hiding this comment

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

I don't understand this change, as dir(options) will not return None even when options is None.

Removed the code modifications and the tests passes with no problems.

Tried other tests to understand when it fails and why, but they all pass:

    @mock.patch("builtins.dir")
    def test_new_handles_null_options(self, mock_dir):
        # #1163 - simulates a call to dir() returning additional attributes
        mock_dir.return_value = None
        MyResource()

    @mock.patch("builtins.dir")
    def test_new_handles_null_options(self, mock_dir):
        # #1163 - simulates a call to dir() returning additional attributes
        mock_dir.return_value = []
        MyResource()

@matthewhegarty
Copy link
Contributor Author

Hi Manel, thanks for reviewing.

The issue only occurs when the forbiddenfruit library is installed. If it is installed, a call to dir(None) returns extra attributes (eg 'attrs') which means that the option.startswith('_') check fails, then the crash occurs because there is a call to setattr(meta, option, getattr(options, option)), with getattr() being called with a null options reference.

The test has to simulate returning values from dir(None) which don't start with a leading underscore, because this is what forbiddenfruit is doing.

Removed the code modifications and the tests passes with no problems.

It will be fine unless you install forbiddenfruit, because the issue only occurs in conjunction with that. It's easy to reproduce.

@manelclos
Copy link
Contributor

Hi Matthew, I see. I spent some more time checking and found that you need a base class to trigger the code we want to test, something like this does the trick:

    @mock.patch("builtins.dir")
    def test_new_handles_null_options(self, mock_dir):
        # #1163 - simulates a call to dir() returning additional attributes
        mock_dir.return_value = ['attrs']
        class A(MyResource):
            pass

        A()

Then, options is not Falsy, so the code needs to be changed to something like this:

                for option in [option for option in dir(options)
                               if not option.startswith('_') and hasattr(options, option)]:

Once I made these changes it makes sense.

Let me know what you think.

@matthewhegarty matthewhegarty force-pushed the tests_fail_with_forbiddenfruit_imported_issue_1163 branch from 387ed56 to 7a6ecb7 Compare September 15, 2021 11:29
@matthewhegarty
Copy link
Contributor Author

matthewhegarty commented Sep 15, 2021

Looks good - thank you for those suggestions - I've added that in.
I tested as well with the forbiddenfruit lib installed.

Copy link
Contributor

@manelclos manelclos left a comment

Choose a reason for hiding this comment

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

LGTM

@matthewhegarty matthewhegarty merged commit 86f169e into django-import-export:main Sep 15, 2021
@matthewhegarty matthewhegarty deleted the tests_fail_with_forbiddenfruit_imported_issue_1163 branch February 22, 2023 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants