Show More
@@ -2793,7 +2793,10 b' def debugwireproto(ui, repo, path=None, ' | |||||
2793 | or a flag name for stream flags or frame flags, respectively. Values are |
|
2793 | or a flag name for stream flags or frame flags, respectively. Values are | |
2794 | resolved to integers and then bitwise OR'd together. |
|
2794 | resolved to integers and then bitwise OR'd together. | |
2795 |
|
2795 | |||
2796 | ``payload`` is is evaluated as a Python byte string literal. |
|
2796 | ``payload`` represents the raw frame payload. If it begins with | |
|
2797 | ``cbor:``, the following string is evaluated as Python code and the | |||
|
2798 | resulting object is fed into a CBOR encoder. Otherwise it is interpreted | |||
|
2799 | as a Python byte string literal. | |||
2797 | """ |
|
2800 | """ | |
2798 | opts = pycompat.byteskwargs(opts) |
|
2801 | opts = pycompat.byteskwargs(opts) | |
2799 |
|
2802 |
@@ -9,6 +9,7 b'' | |||||
9 |
|
9 | |||
10 | from __future__ import absolute_import |
|
10 | from __future__ import absolute_import | |
11 |
|
11 | |||
|
12 | import __future__ | |||
12 | import codecs |
|
13 | import codecs | |
13 | import re as remod |
|
14 | import re as remod | |
14 | import textwrap |
|
15 | import textwrap | |
@@ -497,3 +498,29 b' def parsebool(s):' | |||||
497 | If s is not a valid boolean, returns None. |
|
498 | If s is not a valid boolean, returns None. | |
498 | """ |
|
499 | """ | |
499 | return _booleans.get(s.lower(), None) |
|
500 | return _booleans.get(s.lower(), None) | |
|
501 | ||||
|
502 | def evalpython(s): | |||
|
503 | """Evaluate a string containing a Python expression. | |||
|
504 | ||||
|
505 | THIS FUNCTION IS NOT SAFE TO USE ON UNTRUSTED INPUT. IT'S USE SHOULD BE | |||
|
506 | LIMITED TO DEVELOPER-FACING FUNCTIONALITY. | |||
|
507 | """ | |||
|
508 | globs = { | |||
|
509 | r'__builtins__': { | |||
|
510 | r'None': None, | |||
|
511 | r'False': False, | |||
|
512 | r'True': True, | |||
|
513 | r'int': int, | |||
|
514 | r'set': set, | |||
|
515 | r'tuple': tuple, | |||
|
516 | # Don't need to expose dict and list because we can use | |||
|
517 | # literals. | |||
|
518 | }, | |||
|
519 | } | |||
|
520 | ||||
|
521 | # We can't use eval() directly because it inherits compiler | |||
|
522 | # flags from this module and we need unicode literals for Python 3 | |||
|
523 | # compatibility. | |||
|
524 | code = compile(s, r'<string>', r'eval', | |||
|
525 | __future__.unicode_literals.compiler_flag, True) | |||
|
526 | return eval(code, globs, {}) |
@@ -16,6 +16,7 b' import struct' | |||||
16 | from .i18n import _ |
|
16 | from .i18n import _ | |
17 | from .thirdparty import ( |
|
17 | from .thirdparty import ( | |
18 | attr, |
|
18 | attr, | |
|
19 | cbor, | |||
19 | ) |
|
20 | ) | |
20 | from . import ( |
|
21 | from . import ( | |
21 | error, |
|
22 | error, | |
@@ -156,6 +157,9 b' def makeframe(requestid, streamid, strea' | |||||
156 | def makeframefromhumanstring(s): |
|
157 | def makeframefromhumanstring(s): | |
157 | """Create a frame from a human readable string |
|
158 | """Create a frame from a human readable string | |
158 |
|
159 | |||
|
160 | DANGER: NOT SAFE TO USE WITH UNTRUSTED INPUT BECAUSE OF POTENTIAL | |||
|
161 | eval() USAGE. DO NOT USE IN CORE. | |||
|
162 | ||||
159 | Strings have the form: |
|
163 | Strings have the form: | |
160 |
|
164 | |||
161 | <request-id> <stream-id> <stream-flags> <type> <flags> <payload> |
|
165 | <request-id> <stream-id> <stream-flags> <type> <flags> <payload> | |
@@ -169,6 +173,11 b' def makeframefromhumanstring(s):' | |||||
169 | named constant. |
|
173 | named constant. | |
170 |
|
174 | |||
171 | Flags can be delimited by `|` to bitwise OR them together. |
|
175 | Flags can be delimited by `|` to bitwise OR them together. | |
|
176 | ||||
|
177 | If the payload begins with ``cbor:``, the following string will be | |||
|
178 | evaluated as Python code and the resulting object will be fed into | |||
|
179 | a CBOR encoder. Otherwise, the payload is interpreted as a Python | |||
|
180 | byte string literal. | |||
172 | """ |
|
181 | """ | |
173 | fields = s.split(b' ', 5) |
|
182 | fields = s.split(b' ', 5) | |
174 | requestid, streamid, streamflags, frametype, frameflags, payload = fields |
|
183 | requestid, streamid, streamflags, frametype, frameflags, payload = fields | |
@@ -196,7 +205,11 b' def makeframefromhumanstring(s):' | |||||
196 | else: |
|
205 | else: | |
197 | finalflags |= int(flag) |
|
206 | finalflags |= int(flag) | |
198 |
|
207 | |||
199 | payload = stringutil.unescapestr(payload) |
|
208 | if payload.startswith(b'cbor:'): | |
|
209 | payload = cbor.dumps(stringutil.evalpython(payload[5:]), canonical=True) | |||
|
210 | ||||
|
211 | else: | |||
|
212 | payload = stringutil.unescapestr(payload) | |||
200 |
|
213 | |||
201 | return makeframe(requestid=requestid, streamid=streamid, |
|
214 | return makeframe(requestid=requestid, streamid=streamid, | |
202 | streamflags=finalstreamflags, typeid=frametype, |
|
215 | streamflags=finalstreamflags, typeid=frametype, |
@@ -35,6 +35,59 b' def sendcommandframes(reactor, stream, r' | |||||
35 | framing.createcommandframes(stream, rid, cmd, args, |
|
35 | framing.createcommandframes(stream, rid, cmd, args, | |
36 | datafh)) |
|
36 | datafh)) | |
37 |
|
37 | |||
|
38 | class FrameHumanStringTests(unittest.TestCase): | |||
|
39 | def testbasic(self): | |||
|
40 | self.assertEqual(ffs(b'1 1 0 1 0 '), | |||
|
41 | b'\x00\x00\x00\x01\x00\x01\x00\x10') | |||
|
42 | ||||
|
43 | self.assertEqual(ffs(b'2 4 0 1 0 '), | |||
|
44 | b'\x00\x00\x00\x02\x00\x04\x00\x10') | |||
|
45 | ||||
|
46 | self.assertEqual(ffs(b'2 4 0 1 0 foo'), | |||
|
47 | b'\x03\x00\x00\x02\x00\x04\x00\x10foo') | |||
|
48 | ||||
|
49 | def testcborint(self): | |||
|
50 | self.assertEqual(ffs(b'1 1 0 1 0 cbor:15'), | |||
|
51 | b'\x01\x00\x00\x01\x00\x01\x00\x10\x0f') | |||
|
52 | ||||
|
53 | self.assertEqual(ffs(b'1 1 0 1 0 cbor:42'), | |||
|
54 | b'\x02\x00\x00\x01\x00\x01\x00\x10\x18*') | |||
|
55 | ||||
|
56 | self.assertEqual(ffs(b'1 1 0 1 0 cbor:1048576'), | |||
|
57 | b'\x05\x00\x00\x01\x00\x01\x00\x10\x1a' | |||
|
58 | b'\x00\x10\x00\x00') | |||
|
59 | ||||
|
60 | self.assertEqual(ffs(b'1 1 0 1 0 cbor:0'), | |||
|
61 | b'\x01\x00\x00\x01\x00\x01\x00\x10\x00') | |||
|
62 | ||||
|
63 | self.assertEqual(ffs(b'1 1 0 1 0 cbor:-1'), | |||
|
64 | b'\x01\x00\x00\x01\x00\x01\x00\x10 ') | |||
|
65 | ||||
|
66 | self.assertEqual(ffs(b'1 1 0 1 0 cbor:-342542'), | |||
|
67 | b'\x05\x00\x00\x01\x00\x01\x00\x10:\x00\x05:\r') | |||
|
68 | ||||
|
69 | def testcborstrings(self): | |||
|
70 | # String literals should be unicode. | |||
|
71 | self.assertEqual(ffs(b"1 1 0 1 0 cbor:'foo'"), | |||
|
72 | b'\x04\x00\x00\x01\x00\x01\x00\x10cfoo') | |||
|
73 | ||||
|
74 | self.assertEqual(ffs(b"1 1 0 1 0 cbor:b'foo'"), | |||
|
75 | b'\x04\x00\x00\x01\x00\x01\x00\x10Cfoo') | |||
|
76 | ||||
|
77 | self.assertEqual(ffs(b"1 1 0 1 0 cbor:u'foo'"), | |||
|
78 | b'\x04\x00\x00\x01\x00\x01\x00\x10cfoo') | |||
|
79 | ||||
|
80 | def testcborlists(self): | |||
|
81 | self.assertEqual(ffs(b"1 1 0 1 0 cbor:[None, True, False, 42, b'foo']"), | |||
|
82 | b'\n\x00\x00\x01\x00\x01\x00\x10\x85\xf6\xf5\xf4' | |||
|
83 | b'\x18*Cfoo') | |||
|
84 | ||||
|
85 | def testcbordicts(self): | |||
|
86 | self.assertEqual(ffs(b"1 1 0 1 0 " | |||
|
87 | b"cbor:{b'foo': b'val1', b'bar': b'val2'}"), | |||
|
88 | b'\x13\x00\x00\x01\x00\x01\x00\x10\xa2' | |||
|
89 | b'CbarDval2CfooDval1') | |||
|
90 | ||||
38 | class FrameTests(unittest.TestCase): |
|
91 | class FrameTests(unittest.TestCase): | |
39 | def testdataexactframesize(self): |
|
92 | def testdataexactframesize(self): | |
40 | data = util.bytesio(b'x' * framing.DEFAULT_MAX_FRAME_SIZE) |
|
93 | data = util.bytesio(b'x' * framing.DEFAULT_MAX_FRAME_SIZE) |
General Comments 0
You need to be logged in to leave comments.
Login now