Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.

Bug 1528775

Summary: Python hashlib changes means Django will not work for SCL Python 3.6.
Product: Red Hat Software Collections Reporter: Graham Dumpleton <gdumplet>
Component: pythonAssignee: Python Maintainers <python-maint>
Status: CLOSED DUPLICATE QA Contact: BaseOS QE - Apps <qe-baseos-apps>
Severity: medium Docs Contact:
Priority: unspecified    
Version: rh-python36CC: cheimes, cstratak, fweimer, gdumplet, hhorak, pviktori
Target Milestone: alpha   
Target Release: 3.1   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2018-01-04 11:48:31 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Graham Dumpleton 2017-12-23 21:34:39 UTC
Description of problem:

Changes made to the hashlib module included in the Python standard library as part of SCL Python 3.6 will prevent use of Django with that Python version.

Version-Release number of selected component (if applicable):

SCL Python 3.6

How reproducible:

Always.

Steps to Reproduce:

The problem is exhibited with the following small test case.

import hashlib

class Test:
    digest = hashlib.sha256

    def check(self):
        print(self.digest)

    def name(self):
        print(self.digest().name)

t = Test()

t.check()
t.name()

Run this with SCL Python 3.5, or any non SCL Python 3.6 distribution and it will work fine.

If run with SCL Python 3.6, it fails.

Actual results:

$ python3.6 bug.py
<bound method openssl_sha256 of <__main__.Test object at 0x7f437c2616a0>>
Traceback (most recent call last):
  File "bug.py", line 15, in <module>
    t.name()
  File "bug.py", line 10, in name
    print(self.digest().name)
  File "/opt/app-root/lib64/python3.6/hashlib.py", line 90, in inner
    return func(*args, **kwargs)
TypeError: object supporting the buffer API required

Expected results:

$ python3.6 bug.py
<built-in function openssl_sha256>
sha256

Additional info:

The way this breaks Django is that it isn't possible to create a super user account for Django by running 'python manage.py createsuperuser'.

This will be a significant problem for OpenShift where SCL Python 3.6 is used in the S2I builder for Python 3.6. When this S2I builder makes its way into OpenShift Online and other OpenShift 3.7 installations, it will not be possible to create those users when using Django, forcing users to go back to using Python 3.5.

An issue has also been created against OpenShift Python S2I builder image at:

* https://github.com/sclorg/s2i-python-container/issues/237

The problem code in the hashlib changes made for SCL are:

# Code in hashlib.py which causes issue.

import functools
def __ignore_usedforsecurity(func):
    """Used for sha3_* functions. Until OpenSSL implements them, we want
    to use them from Python _sha3 module, but we want them to accept
    usedforsecurity argument too."""
    # TODO: remove this function when OpenSSL implements sha3
    @functools.wraps(func)
    def inner(*args, **kwargs):
        if 'usedforsecurity' in kwargs:
            kwargs.pop('usedforsecurity')
        return func(*args, **kwargs)
    return inner
 
  ....
  
  for __func_name in __always_supported:
    # try them all, some may not work due to the OpenSSL
    # version not supporting that algorithm.
    try:
        func = __get_hash(__func_name)
        if 'sha3_' or 'blake2' or 'shake_' in __func_name:
            func = __ignore_usedforsecurity(func)
        globals()[__func_name] = func
    except ValueError:
        import logging
        logging.exception('code for hash %s was not found.', __func_name)

The simplistic decorator implementation fails when used in a situation where method binding against None occurs, which happens when function with decorator applied is saved as class attribute and then accessed via self.

Comment 2 Honza Horak 2018-01-02 14:54:07 UTC
So, why Python 3.6 SCL behaves differently than other 3.6 builds or other versions? Is it an upstream bug fixed in newest build or does the SCL do something differently?

Comment 3 Graham Dumpleton 2018-01-02 19:55:57 UTC
It appears to specially be something done in SCL Python 3.6.

Comment 4 Petr Viktorin (pviktori) 2018-01-03 12:48:24 UTC
I'll look into this tomorrow, preferably with Harris.

Comment 5 Charalampos Stratakis 2018-01-03 13:18:15 UTC
Seems to be a symptom of the same issue. See also bug 1497342

Comment 6 Charalampos Stratakis 2018-01-03 15:58:44 UTC
So as it seems from https://bugzilla.redhat.com/show_bug.cgi?id=1497342#c12 this is due to wrongly evaluated expression.

With:

if 'sha3_' or 'blake2' or 'shake_' in __func_name:

only the shake algorithm is tested if it exists within the __func_name.

This can be fixed be either using the solution mentioned in the comment or changing that line to something like:

if ('sha3_' or 'blake2' or 'shake_') in __func_name:

Already tested some builds and the reproducers from this bug and bug 1497342 verify the fix.

Graham are you ok with marking this bug as duplicate of bug 1497342 as it's older and contains a proposed fix?

Comment 7 Petr Viktorin (pviktori) 2018-01-03 16:01:11 UTC
Go with Josko Plazonic's solution, ('sha3_' or 'blake2' or 'shake_') in __func_name is also wrong.

Comment 8 Christian Heimes 2018-01-03 16:06:04 UTC
How about __func_name.startswith(('sha3_', 'blake2', 'shake_'))?

Comment 9 Graham Dumpleton 2018-01-03 21:50:31 UTC
If you have already confirmed that the fix for the other issue also fixes this issue by running the test script included here, by all means close this issue in favour of the other.

Comment 10 Charalampos Stratakis 2018-01-04 11:48:31 UTC

*** This bug has been marked as a duplicate of bug 1497342 ***