The wolfCrypt and wolfSSL Python wrappers are maintained in the
wolfCrypt-py and wolfSSL-py trees respectively. The duplicates in this
tree are stale. The content has been checked and any important changes
have been ported over to their respective trees.
During interpreter shutdown, depending on the order in which things happen, a module can be unloaded before all instances of classes defined in that module are garbage collected.
In particular, this means that any global variables (including imported modules) become `None` by the time the instances `__del__` is called, resulting in
```
AttributeError: 'NoneType' object has no attribute 'wc_FreeRng'
```
being displayed while the process exits. This can be avoided simply by catching and ignoring the `AttributeError` in this case, since the process is shutting down anyways.
Python's bytecode compiler has a peephole optimizer which, among other things, can recognize constant expressions and replace them with a constant.
In `Random.byte` the expression `t2b('\0')` is recognized as a constant and is replaced with a single constant compiled into the function's bytecode.
This means that every time you run `Random.byte`, rather than creating a new `str` object (or `bytes` in Python 3) it's reusing the same one each time, and `wc_RNG_GenerateByte` is writing right into that constant object's buffer; hence the following behavior:
```
In [55]: rng = Random()
In [56]: a = rng.byte()
In [57]: a
Out[57]: "'"
In [58]: rng.byte()
Out[58]: '\x11'
In [59]: a
Out[59]: '\x11'
In [60]: rng.byte()
Out[60]: '\x16'
In [61]: a
Out[61]: '\x16'
In [62]: rng.byte.__func__.__code__.co_consts
Out[62]:
('\n Generate and return a random byte.\n ',
'\x16',
0,
'RNG generate byte error (%d)')
In [63]: rng.byte()
Out[63]: '\xad'
In [64]: rng.byte.__func__.__code__.co_consts
Out[64]:
('\n Generate and return a random byte.\n ',
'\xad',
0,
'RNG generate byte error (%d)')
```
`Random.bytes` does not necessarily have this problem since its result buffer is not a constant expression, though I feel like it could also in principle be affected if the string were interned (though I couldn't produce such a result). Nevertheless, it doesn't seem like a good idea to be updating `str` objects' buffers directly.