Skip to content

Initial string changes after quoting and unquoting #1482

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

Open
4 of 5 tasks
lenix123 opened this issue Mar 17, 2025 · 1 comment
Open
4 of 5 tasks

Initial string changes after quoting and unquoting #1482

lenix123 opened this issue Mar 17, 2025 · 1 comment
Labels

Comments

@lenix123
Copy link

Please confirm the following

  • I understand this is open source software provided for free and that I might not receive a timely response.
  • I am positive I am NOT reporting a (potential) security
    vulnerability, to the best of my knowledge. (These must be shared by
    submitting this report form instead, if
    any hesitation exists.)
  • I am willing to submit a pull request with reporoducers as xfailing test cases or even entire fix. (Assign this issue to me.)

Describe the bug

We were fuzzing yarl url quoting. We assumed that input string shouldn't change after url quotinq and unquoting. But using _quoting_py module input string is not equal to output string after quoting and unquoting. If it's not safe to assume that string will not be changed after quoting and unquoting please let us know.

To Reproduce

  1. Install atheris and yarl 1.18.3:
pip install --force-reinstall -v "yarl==1.18.3"
  1. Run our test url_quoter_test.py:
from yarl._quoting_py import _Quoter
from yarl._quoting_py import _Unquoter

data = '%%1111'
quote = _Quoter()
unquote = _Unquoter()
text_quoted = quote(data)
text_output = unquote(text_quoted)
assert data == text_output
python3 url_quoter_fuzz.py crash.raw
  1. See assertion error that input string is not equal to output string.

Expected behavior

input string shouldn't change after url quotinq and unquoting

Logs/tracebacks

Traceback (most recent call last):
  File "/home/fuzzer/fuzz/reproduce.py", line 10, in <module>
    assert data == text_output
AssertionError

Python Version

$ python --version
Python 3.9.20

multidict Version

$ python -m pip show multidict
Name: multidict
Version: 6.1.0
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /usr/local/lib64/python3/site-packages
Requires: typing-extensions
Required-by: yarl

propcache Version

$ python -m pip show propcache
Name: propcache
Version: 0.3.0
Summary: Accelerated property cache
Home-page: https://github.com/aio-libs/propcache
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache-2.0
Location: /usr/local/lib64/python3/site-packages
Requires: 
Required-by: yarl

yarl Version

$ python -m pip show yarl
Name: yarl
Version: 1.18.3
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache-2.0
Location: /usr/local/lib64/python3/site-packages
Requires: idna, multidict, propcache
Required-by:

OS

alt:p10

Additional context

We have found it by fuzzing yarl with atheris. So you can see the full fuzz test:

import atheris
import sys

with atheris.instrument_imports():
    from yarl._quoting_py import _Quoter
    from yarl._quoting_py import _Unquoter


def TestOneInput(input_bytes):
    fdp = atheris.FuzzedDataProvider(input_bytes)
    data = fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)
    print(data)
    try:
        quote = _Quoter()
        unquote = _Unquoter()
        text_quoted = quote(data)
        text_output = unquote(text_quoted)
        assert data == text_output
    except ValueError as e:
        pass

def main():
    atheris.Setup(sys.argv, TestOneInput)
    atheris.Fuzz()

if __name__ == "__main__":
    main()
@lenix123 lenix123 added the bug label Mar 17, 2025
@lenix123
Copy link
Author

There is also a similar problem in Cython implementation of quoting:

from yarl._quoting_c import _Quoter
from yarl._quoting_c import _Unquoter

data = '%22'
quote = _Quoter()
unquote = _Unquoter()
text_quoted = quote(data)
text_output = unquote(text_quoted)
assert data == text_output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant