Show More
@@ -1283,6 +1283,27 b' def optimize(x, small):' | |||||
1283 | return w + wa, (op, x[1], ta) |
|
1283 | return w + wa, (op, x[1], ta) | |
1284 | return 1, x |
|
1284 | return 1, x | |
1285 |
|
1285 | |||
|
1286 | _aliasarg = ('func', ('symbol', '_aliasarg')) | |||
|
1287 | def _getaliasarg(tree): | |||
|
1288 | """If tree matches ('func', ('symbol', '_aliasarg'), ('string', X)) | |||
|
1289 | return X, None otherwise. | |||
|
1290 | """ | |||
|
1291 | if (len(tree) == 3 and tree[:2] == _aliasarg | |||
|
1292 | and tree[2][0] == 'string'): | |||
|
1293 | return tree[2][1] | |||
|
1294 | return None | |||
|
1295 | ||||
|
1296 | def _checkaliasarg(tree, known=None): | |||
|
1297 | """Check tree contains no _aliasarg construct or only ones which | |||
|
1298 | value is in known. Used to avoid alias placeholders injection. | |||
|
1299 | """ | |||
|
1300 | if isinstance(tree, tuple): | |||
|
1301 | arg = _getaliasarg(tree) | |||
|
1302 | if arg is not None and (not known or arg not in known): | |||
|
1303 | raise error.ParseError(_("not a function: %s") % '_aliasarg') | |||
|
1304 | for t in tree: | |||
|
1305 | _checkaliasarg(t, known) | |||
|
1306 | ||||
1286 | class revsetalias(object): |
|
1307 | class revsetalias(object): | |
1287 | funcre = re.compile('^([^(]+)\(([^)]+)\)$') |
|
1308 | funcre = re.compile('^([^(]+)\(([^)]+)\)$') | |
1288 | args = None |
|
1309 | args = None | |
@@ -1299,7 +1320,9 b' class revsetalias(object):' | |||||
1299 | self.tree = ('func', ('symbol', m.group(1))) |
|
1320 | self.tree = ('func', ('symbol', m.group(1))) | |
1300 | self.args = [x.strip() for x in m.group(2).split(',')] |
|
1321 | self.args = [x.strip() for x in m.group(2).split(',')] | |
1301 | for arg in self.args: |
|
1322 | for arg in self.args: | |
1302 | value = value.replace(arg, repr(arg)) |
|
1323 | # _aliasarg() is an unknown symbol only used separate | |
|
1324 | # alias argument placeholders from regular strings. | |||
|
1325 | value = value.replace(arg, '_aliasarg(%r)' % (arg,)) | |||
1303 | else: |
|
1326 | else: | |
1304 | self.name = name |
|
1327 | self.name = name | |
1305 | self.tree = ('symbol', name) |
|
1328 | self.tree = ('symbol', name) | |
@@ -1307,6 +1330,8 b' class revsetalias(object):' | |||||
1307 | self.replacement, pos = parse(value) |
|
1330 | self.replacement, pos = parse(value) | |
1308 | if pos != len(value): |
|
1331 | if pos != len(value): | |
1309 | raise error.ParseError(_('invalid token'), pos) |
|
1332 | raise error.ParseError(_('invalid token'), pos) | |
|
1333 | # Check for placeholder injection | |||
|
1334 | _checkaliasarg(self.replacement, self.args) | |||
1310 |
|
1335 | |||
1311 | def _getalias(aliases, tree): |
|
1336 | def _getalias(aliases, tree): | |
1312 | """If tree looks like an unexpanded alias, return it. Return None |
|
1337 | """If tree looks like an unexpanded alias, return it. Return None | |
@@ -1327,13 +1352,14 b' def _getalias(aliases, tree):' | |||||
1327 | return None |
|
1352 | return None | |
1328 |
|
1353 | |||
1329 | def _expandargs(tree, args): |
|
1354 | def _expandargs(tree, args): | |
1330 | """Replace all occurences of ('string', name) with the |
|
1355 | """Replace _aliasarg instances with the substitution value of the | |
1331 |
s |
|
1356 | same name in args, recursively. | |
1332 | """ |
|
1357 | """ | |
1333 | if not isinstance(tree, tuple): |
|
1358 | if not tree or not isinstance(tree, tuple): | |
1334 | return tree |
|
1359 | return tree | |
1335 | if len(tree) == 2 and tree[0] == 'string': |
|
1360 | arg = _getaliasarg(tree) | |
1336 | return args.get(tree[1], tree) |
|
1361 | if arg is not None: | |
|
1362 | return args[arg] | |||
1337 | return tuple(_expandargs(t, args) for t in tree) |
|
1363 | return tuple(_expandargs(t, args) for t in tree) | |
1338 |
|
1364 | |||
1339 | def _expandaliases(aliases, tree, expanding): |
|
1365 | def _expandaliases(aliases, tree, expanding): | |
@@ -1367,6 +1393,7 b' def _expandaliases(aliases, tree, expand' | |||||
1367 | return result |
|
1393 | return result | |
1368 |
|
1394 | |||
1369 | def findaliases(ui, tree): |
|
1395 | def findaliases(ui, tree): | |
|
1396 | _checkaliasarg(tree) | |||
1370 | aliases = {} |
|
1397 | aliases = {} | |
1371 | for k, v in ui.configitems('revsetalias'): |
|
1398 | for k, v in ui.configitems('revsetalias'): | |
1372 | alias = revsetalias(k, v) |
|
1399 | alias = revsetalias(k, v) |
@@ -558,6 +558,19 b' far away.' | |||||
558 | abort: unknown revision '$1'! |
|
558 | abort: unknown revision '$1'! | |
559 | [255] |
|
559 | [255] | |
560 |
|
560 | |||
|
561 | $ echo 'injectparamasstring2 = max(_aliasarg("$1"))' >> .hg/hgrc | |||
|
562 | $ echo 'callinjection2($1) = descendants(injectparamasstring2)' >> .hg/hgrc | |||
|
563 | $ try 'callinjection2(2:5)' | |||
|
564 | (func | |||
|
565 | ('symbol', 'callinjection2') | |||
|
566 | (range | |||
|
567 | ('symbol', '2') | |||
|
568 | ('symbol', '5'))) | |||
|
569 | hg: parse error: not a function: _aliasarg | |||
|
570 | [255] | |||
|
571 | >>> data = file('.hg/hgrc', 'rb').read() | |||
|
572 | >>> file('.hg/hgrc', 'wb').write(data.replace('_aliasarg', '')) | |||
|
573 | ||||
561 | $ try 'd(2:5)' |
|
574 | $ try 'd(2:5)' | |
562 | (func |
|
575 | (func | |
563 | ('symbol', 'd') |
|
576 | ('symbol', 'd') |
General Comments 0
You need to be logged in to leave comments.
Login now