Show More
@@ -2793,7 +2793,10 b' def debugwireproto(ui, repo, path=None, ' | |||
|
2793 | 2793 | or a flag name for stream flags or frame flags, respectively. Values are |
|
2794 | 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 | 2801 | opts = pycompat.byteskwargs(opts) |
|
2799 | 2802 |
@@ -9,6 +9,7 b'' | |||
|
9 | 9 | |
|
10 | 10 | from __future__ import absolute_import |
|
11 | 11 | |
|
12 | import __future__ | |
|
12 | 13 | import codecs |
|
13 | 14 | import re as remod |
|
14 | 15 | import textwrap |
@@ -497,3 +498,29 b' def parsebool(s):' | |||
|
497 | 498 | If s is not a valid boolean, returns None. |
|
498 | 499 | """ |
|
499 | 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 | 16 | from .i18n import _ |
|
17 | 17 | from .thirdparty import ( |
|
18 | 18 | attr, |
|
19 | cbor, | |
|
19 | 20 | ) |
|
20 | 21 | from . import ( |
|
21 | 22 | error, |
@@ -156,6 +157,9 b' def makeframe(requestid, streamid, strea' | |||
|
156 | 157 | def makeframefromhumanstring(s): |
|
157 | 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 | 163 | Strings have the form: |
|
160 | 164 | |
|
161 | 165 | <request-id> <stream-id> <stream-flags> <type> <flags> <payload> |
@@ -169,6 +173,11 b' def makeframefromhumanstring(s):' | |||
|
169 | 173 | named constant. |
|
170 | 174 | |
|
171 | 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 | 182 | fields = s.split(b' ', 5) |
|
174 | 183 | requestid, streamid, streamflags, frametype, frameflags, payload = fields |
@@ -196,7 +205,11 b' def makeframefromhumanstring(s):' | |||
|
196 | 205 | else: |
|
197 | 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 | 214 | return makeframe(requestid=requestid, streamid=streamid, |
|
202 | 215 | streamflags=finalstreamflags, typeid=frametype, |
@@ -35,6 +35,59 b' def sendcommandframes(reactor, stream, r' | |||
|
35 | 35 | framing.createcommandframes(stream, rid, cmd, args, |
|
36 | 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 | 91 | class FrameTests(unittest.TestCase): |
|
39 | 92 | def testdataexactframesize(self): |
|
40 | 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