Skip to content
File

Blob: src/pyodide/internal/topLevelEntropy/allow_entropy.py

python61 lines
1# Control number of allowed entropy calls.
2import sys
3from array import array
4from contextlib import contextmanager
5 
6ALLOWED_ENTROPY_CALLS = array("b", [0])
7IN_REQUEST_CONTEXT = False
8 
9 
10def in_request_context():
11 return IN_REQUEST_CONTEXT
12 
13 
14def _set_in_request_context():
15 global IN_REQUEST_CONTEXT
16 
17 IN_REQUEST_CONTEXT = True
18 
19 
20def should_allow_entropy_call():
21 """This helps us raise Python errors rather than fatal errors in some cases.
22
23 It doesn't really matter that much since we're not likely to recover from
24 these anyways but it feels better.
25 """
26 # Allow if we've either entered request context or if we've temporarily
27 # enabled entropy.
28 return IN_REQUEST_CONTEXT or is_bad_entropy_enabled()
29 
30 
31def raise_unless_entropy_allowed():
32 if not should_allow_entropy_call():
33 EIO = 29
34 raise OSError(EIO, "Cannot get entropy outside of request context")
35 
36 
37def get_bad_entropy_flag():
38 # simpleRunPython reads out stderr. We put the address there so we can fish
39 # it out... We could use ctypes instead of array but ctypes weighs an extra
40 # 100kb compared to array.
41 print(ALLOWED_ENTROPY_CALLS.buffer_info()[0], file=sys.stderr)
42 
43 
44def is_bad_entropy_enabled():
45 """This is used in entropy_patches.py to let calls to disabled functions
46 through if we are allowing bad entropy
47 """
48 return ALLOWED_ENTROPY_CALLS[0] > 0
49 
50 
51@contextmanager
52def allow_bad_entropy_calls(n):
53 old_allowed_entropy_calls = ALLOWED_ENTROPY_CALLS[0]
54 ALLOWED_ENTROPY_CALLS[0] = n
55 yield
56 if ALLOWED_ENTROPY_CALLS[0] > 0:
57 raise RuntimeError(
58 f"{ALLOWED_ENTROPY_CALLS[0]} unexpected leftover getentropy calls "
59 )
60 ALLOWED_ENTROPY_CALLS[0] = old_allowed_entropy_calls