framebuf.FrameBuffer: not secured against silly/wrong/malicious strides
Dear Micropython Developers!
framebuf.FrameBuffer is not secured against the misuse with unreasonable values of the stride parameter.
IMHO :
- stride < width is nonsense (or only useful for esoteric matters) and should be set to width
- strides larger than len(buf)/width are an attack vector to disclose information
So this can happen:
buffer = bytearray([0, 0, 0, 0, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
for stride in range(100):
fb = framebuf.FrameBuffer(buffer, 2, 2, framebuf.MONO_HLSB, stride)
a = fb.pixel(1,1)
print(stride, a)
The function getpixel should only operate in the buffers first four bytes, thus only returning zero values.
But the bit pattern of the wider buffer is exposed.
>>> %Run -c $EDITOR_CONTENT
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 0
15 0
16 0
17 0
18 0
19 0
20 0
21 0
22 0
23 0
24 0
25 1
26 1
27 1
28 1
29 1
30 1
31 1
32 1
33 0
34 0
35 0
36 0
37 0
38 0
39 0
40 0
41 1
42 1
43 1
44 1
45 1
46 1
47 1
48 1
49 1
50 1
51 1
52 1
53 1
54 1
55 1
56 1
57 1
58 1
59 1
60 1
61 1
62 1
63 1
64 1
65 1
66 1
67 1
68 1
69 1
70 1
71 1
72 1
73 1
74 1
75 1
76 1
77 1
78 1
79 1
80 1
81 1
82 1
83 1
84 1
85 1
86 1
87 1
88 1
89 0
90 0
91 0
92 0
93 0
94 0
95 0
96 0
97 0
98 0
99 0
This allows a malicious code to read arbitrary RAM positions.
To prevent this there should be checks for dangerous stride values while creating a FrameBuffer instance.
I noticed this while bringing up my testing for the new FrameBuffer.get_rect() routine.
Also there is not a single test in the existing framebuf testing code concerning the stride parameter.
Sorry for counting peas.
Cheers,
Volker
extmod/modframebuf: Validate framebuf bounds against buffer.
Fixes #12562 and #12563. cc @gwangmu
I'm not sure why FrameBuffer never validated these arguments, I guess maybe as a code size optimisation but I think this is a useful thing to guard against accidental mistakes and improve usability / reduce confusion as debugging "why doesn't the display look right" can be quite difficult.
Also fixes the length calculation in framebuf_get_buffer which was completely wrong for most formats as it did not take into account the bits-per-pixel. (Edit: Rather than fixing this, just make it forward directly to the underlying buffer)
This ensures that the buffer is large enough for the specified width, height, bits-per-pixel, and stride.
Also makes the legacy FrameBuffer1 constructor re-use the FrameBuffer make_new to save some code size and hopefully offset this a bit.
This work was funded through GitHub Sponsors.