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

Raise BadRequestKeyError in MultiDict.__getitem__ when internal list is empty #979

Closed
alexpantyukhin opened this issue Aug 6, 2016 · 10 comments
Labels

Comments

@alexpantyukhin
Copy link
Contributor

I think that it would be logically to raise BadRequestKeyError there https://github.com/pallets/werkzeug/blob/master/werkzeug/datastructures.py#L402 when the list of values is empty.

@untitaker
Copy link
Contributor

Why do you think this is better behavior?

@alexpantyukhin
Copy link
Contributor Author

It's possible to set empty values list for specified key. And then if the consumer of the MultiDict tries to get item by key he gets IndexError: list index out of range. I believe this is not good because the consumer see exception from the internal
implementation which uses lists and doesn't show exactly consumer did wrong. Also I think that actually MultiDict should not allow to set empty lists or remove specified keys from the instance when empty lists are passed.

@untitaker
Copy link
Contributor

That makes sense. I'm leaning a bit more towards skipping empty lists in init

@davidism
Copy link
Member

I like that idea more. In the case of a multi dict, setting an empty list for the key seems equivalent to not setting the key at all.

@alexpantyukhin
Copy link
Contributor Author

@davidism Do you mean remove key (if it already exists) if empty list was passed, right?

If yes then the suggestion:
- skip keys with empty lists in the __init__ method.
- remove key if empty list was passed in the __setitem__ method
- the same for the setlist method

The question is only about setlistdefault. it could be returned and extended later, and there is no way to make user populate the list before getitem.

@untitaker
Copy link
Contributor

skip keys with empty lists in the __init__ method.

👍

remove key if empty list was passed in the __setitem__ method

Why? __setitem__ always sets a single-value list with the given object.

the same for the setlist method

That makes sense.

I don't understand why setlistdefault needs any change either.

@untitaker
Copy link
Contributor

To be clear, to me this is more about not letting MultiDict come in an invalid state where __getitem__ would crash like you described, not a general API revamp.

@alexpantyukhin
Copy link
Contributor Author

@untitaker Sorry about the second point I was inattentive. Actually yes. In this case it will have at least one value anyway

@alexpantyukhin
Copy link
Contributor Author

alexpantyukhin commented Aug 19, 2016

If pass empty list to default_list into the setlistdefault method it stores it. When you try to __getitem__ for this key later you will get the IndexError exception.

d = MultiDict([])
d.setlistdefault('a', [])
print d['a']

But it could be already used like that:

d = MultiDict([])
lst = d.setlistdefault('a', [])
lst.extend([2, 3])
print d['a']

In this case I just want show that setlistdefault could be extended later and I can't see now how to not allow to get invalid state for the Multidict in this case.

@untitaker
Copy link
Contributor

untitaker commented Aug 19, 2016

Ah, I understand. I agree... in that case I guess the modification should be done in __getitem__ rather than __init__

untitaker added a commit that referenced this issue Aug 28, 2016
psivesely pushed a commit to freedomofpress/securedrop that referenced this issue Aug 31, 2016
Normally, we're hesistant to issue an update for dependencies when we've already
entered the release candidate(s) stage of the release process. In this case, the
changes I'm adding are all minor bug fixes that I've reviewed. Two of the fixes
were labeled as security issues, however, they don't really affect us as
explained below.

* Werkzeug
  * A bug that allowed XSS attacks on the debug page has been fixed (we
    don't run Flask in debug mode in production) -
    pallets/werkzeug#1001
  * Invalid Content-Type makes for parsing throw ValueError exception (the fix
    returns an invalid request 400 Bad Request page instead of an internal
    server error when the content-type field of a HTTP request is bad--such as
    ' ' or ',') - pallets/werkzeug#995
  * Raise BadRequestKeyError instead of IndexError in MultiDict when calling
    __getitem__ on a key with an empty associated list of values (Flask returns
    forms and query strings as MultiDicts. This is just better error-handling,
    no real bug being fixed here.) -
    pallets/werkzeug#979

* pytop
  * The string comparison function now no longer leaks string length (shouldn't
    affect SD because the length of our TOTP codes are already known) -
    pyauth/pyotp#28
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants