synapse 2.186.0__py311-none-any.whl → 2.187.1__py311-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of synapse might be problematic. Click here for more details.

synapse/lib/stormtypes.py CHANGED
@@ -3816,13 +3816,13 @@ class Queue(StormType):
3816
3816
  'args': (
3817
3817
  {'name': 'item', 'type': 'prim', 'desc': 'The item being put into the queue.', },
3818
3818
  ),
3819
- 'returns': {'type': 'null', }}},
3819
+ 'returns': {'type': 'int', 'desc': 'The queue offset of the item.'}}},
3820
3820
  {'name': 'puts', 'desc': 'Put multiple items into the Queue.',
3821
3821
  'type': {'type': 'function', '_funcname': '_methQueuePuts',
3822
3822
  'args': (
3823
3823
  {'name': 'items', 'type': 'list', 'desc': 'The items to put into the Queue.', },
3824
3824
  ),
3825
- 'returns': {'type': 'null', }}},
3825
+ 'returns': {'type': 'int', 'desc': 'The queue offset of the first item.'}}},
3826
3826
  {'name': 'gets', 'desc': 'Get multiple items from the Queue as a iterator.',
3827
3827
  'type': {'type': 'function', '_funcname': '_methQueueGets',
3828
3828
  'args': (
@@ -6130,14 +6130,14 @@ class Node(Prim):
6130
6130
  'type': {'type': 'function', '_funcname': '_methNodeAddEdge',
6131
6131
  'args': (
6132
6132
  {'name': 'verb', 'type': 'str', 'desc': 'The edge verb to add.'},
6133
- {'name': 'iden', 'type': 'str', 'desc': 'The node id of the destination node.'},
6133
+ {'name': 'iden', 'type': 'str', 'desc': 'The node iden of the destination node.'},
6134
6134
  ),
6135
6135
  'returns': {'type': 'null', }}},
6136
6136
  {'name': 'delEdge', 'desc': 'Remove a light-weight edge.',
6137
6137
  'type': {'type': 'function', '_funcname': '_methNodeDelEdge',
6138
6138
  'args': (
6139
6139
  {'name': 'verb', 'type': 'str', 'desc': 'The edge verb to remove.'},
6140
- {'name': 'iden', 'type': 'str', 'desc': 'The node id of the destination node to remove.'},
6140
+ {'name': 'iden', 'type': 'str', 'desc': 'The node iden of the destination node to remove.'},
6141
6141
  ),
6142
6142
  'returns': {'type': 'null', }}},
6143
6143
  {'name': 'globtags', 'desc': 'Get a list of the tag components from a Node which match a tag glob expression.',
@@ -6827,11 +6827,11 @@ class Layer(Prim):
6827
6827
  'returns': {'name': 'Yields', 'type': 'list',
6828
6828
  'desc': 'Yields messages describing any index inconsistencies.', }}},
6829
6829
  {'name': 'getStorNode', 'desc': '''
6830
- Retrieve the raw storage node for the specified node id.
6830
+ Retrieve the raw storage node for the specified node iden.
6831
6831
  ''',
6832
6832
  'type': {'type': 'function', '_funcname': 'getStorNode',
6833
6833
  'args': (
6834
- {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node id.'},
6834
+ {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
6835
6835
  ),
6836
6836
  'returns': {'type': 'dict', 'desc': 'The storage node dictionary.', }}},
6837
6837
  {'name': 'liftByProp', 'desc': '''
@@ -6897,7 +6897,7 @@ class Layer(Prim):
6897
6897
  'desc': 'Yields (<n1iden>, <verb>, <n2iden>) tuples', }}},
6898
6898
 
6899
6899
  {'name': 'getEdgesByN1', 'desc': '''
6900
- Yield (verb, n2iden) tuples for any light edges in the layer for the source node id.
6900
+ Yield (verb, n2iden) tuples for any light edges in the layer for the source node iden.
6901
6901
 
6902
6902
  Example:
6903
6903
  Iterate the N1 edges for ``$node``::
@@ -6909,13 +6909,13 @@ class Layer(Prim):
6909
6909
  ''',
6910
6910
  'type': {'type': 'function', '_funcname': 'getEdgesByN1',
6911
6911
  'args': (
6912
- {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node id.'},
6912
+ {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
6913
6913
  ),
6914
6914
  'returns': {'name': 'Yields', 'type': 'list',
6915
6915
  'desc': 'Yields (<verb>, <n2iden>) tuples', }}},
6916
6916
 
6917
6917
  {'name': 'getEdgesByN2', 'desc': '''
6918
- Yield (verb, n1iden) tuples for any light edges in the layer for the target node id.
6918
+ Yield (verb, n1iden) tuples for any light edges in the layer for the target node iden.
6919
6919
 
6920
6920
  Example:
6921
6921
  Iterate the N2 edges for ``$node``::
@@ -6926,10 +6926,26 @@ class Layer(Prim):
6926
6926
  ''',
6927
6927
  'type': {'type': 'function', '_funcname': 'getEdgesByN2',
6928
6928
  'args': (
6929
- {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node id.'},
6929
+ {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
6930
6930
  ),
6931
6931
  'returns': {'name': 'Yields', 'type': 'list',
6932
6932
  'desc': 'Yields (<verb>, <n1iden>) tuples', }}},
6933
+ {'name': 'getNodeData', 'desc': '''
6934
+ Yield (name, valu) tuples for any node data in the layer for the target node iden.
6935
+
6936
+ Example:
6937
+ Iterate the node data for ``$node``::
6938
+
6939
+ for ($name, $valu) in $layer.getNodeData($node.iden()) {
6940
+ $lib.print(`{$name} = {$valu}`)
6941
+ }
6942
+ ''',
6943
+ 'type': {'type': 'function', '_funcname': 'getNodeData',
6944
+ 'args': (
6945
+ {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
6946
+ ),
6947
+ 'returns': {'name': 'Yields', 'type': 'list',
6948
+ 'desc': 'Yields (<name>, <valu>) tuples', }}},
6933
6949
  )
6934
6950
  _storm_typename = 'layer'
6935
6951
  _ismutable = False
@@ -6986,6 +7002,7 @@ class Layer(Prim):
6986
7002
  'getStorNodesByForm': self.getStorNodesByForm,
6987
7003
  'getEdgesByN1': self.getEdgesByN1,
6988
7004
  'getEdgesByN2': self.getEdgesByN2,
7005
+ 'getNodeData': self.getNodeData,
6989
7006
  'getMirrorStatus': self.getMirrorStatus,
6990
7007
  }
6991
7008
 
@@ -7355,6 +7372,15 @@ class Layer(Prim):
7355
7372
  async for item in layr.iterNodeEdgesN2(s_common.uhex(nodeid)):
7356
7373
  yield item
7357
7374
 
7375
+ @stormfunc(readonly=True)
7376
+ async def getNodeData(self, nodeid):
7377
+ nodeid = await tostr(nodeid)
7378
+ layriden = self.valu.get('iden')
7379
+ await self.runt.reqUserCanReadLayer(layriden)
7380
+ layr = self.runt.snap.core.getLayer(layriden)
7381
+ async for item in layr.iterNodeData(s_common.uhex(nodeid)):
7382
+ yield item
7383
+
7358
7384
  @stormfunc(readonly=True)
7359
7385
  async def _methLayerGet(self, name, defv=None):
7360
7386
  return self.valu.get(name, defv)
synapse/lib/version.py CHANGED
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
223
223
  ##############################################################################
224
224
  # The following are touched during the release process by bumpversion.
225
225
  # Do not modify these directly.
226
- version = (2, 186, 0)
226
+ version = (2, 187, 1)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = 'ffa4abc52513d4b8ac592496322227eed9e07dc5'
228
+ commit = 'a75f7b990f6350f9d631f1f92ea5063542458aad'
@@ -18,10 +18,10 @@ import synapse.lib.version as s_version
18
18
 
19
19
  logger = logging.getLogger(__name__)
20
20
 
21
- # This is the regular expression pattern for CPE2.2. It's kind of a hybrid
21
+ # This is the regular expression pattern for CPE 2.2. It's kind of a hybrid
22
22
  # between compatible binding and preferred binding. Differences are here:
23
23
  # - Use only the list of percent encoded values specified by preferred binding.
24
- # This is to ensure it converts properly to CPE2.3.
24
+ # This is to ensure it converts properly to CPE 2.3.
25
25
  # - Add tilde (~) to the UNRESERVED list which removes the need to specify the
26
26
  # PACKED encoding specifically.
27
27
  ALPHA = '[A-Za-z]'
@@ -60,6 +60,14 @@ COMPONENT_LIST = f'''
60
60
  cpe22_regex = regex.compile(f'cpe:/{COMPONENT_LIST}', regex.VERBOSE | regex.IGNORECASE)
61
61
  cpe23_regex = regex.compile(s_scrape._cpe23_regex, regex.VERBOSE | regex.IGNORECASE)
62
62
 
63
+ def isValidCpe22(text):
64
+ rgx = cpe22_regex.fullmatch(text)
65
+ return rgx is not None
66
+
67
+ def isValidCpe23(text):
68
+ rgx = cpe23_regex.fullmatch(text)
69
+ return rgx is not None
70
+
63
71
  def cpesplit(text):
64
72
  part = ''
65
73
  parts = []
@@ -251,9 +259,20 @@ class Cpe22Str(s_types.Str):
251
259
  def _normPyStr(self, valu):
252
260
 
253
261
  text = valu.lower()
262
+
254
263
  if text.startswith('cpe:/'):
264
+
265
+ if not isValidCpe22(text):
266
+ mesg = 'CPE 2.2 string appears to be invalid.'
267
+ raise s_exc.BadTypeValu(mesg=mesg, valu=valu)
268
+
255
269
  parts = chopCpe22(text)
256
270
  elif text.startswith('cpe:2.3:'):
271
+
272
+ if not isValidCpe23(text):
273
+ mesg = 'CPE 2.3 string appears to be invalid.'
274
+ raise s_exc.BadTypeValu(mesg=mesg, valu=valu)
275
+
257
276
  parts = cpesplit(text[8:])
258
277
  else:
259
278
  mesg = 'CPE 2.2 string is expected to start with "cpe:/"'
@@ -261,8 +280,7 @@ class Cpe22Str(s_types.Str):
261
280
 
262
281
  v2_2 = zipCpe22(parts)
263
282
 
264
- rgx = cpe22_regex.match(v2_2)
265
- if rgx is None or rgx.group() != v2_2:
283
+ if not isValidCpe22(v2_2): # pragma: no cover
266
284
  mesg = 'CPE 2.2 string appears to be invalid.'
267
285
  raise s_exc.BadTypeValu(mesg=mesg, valu=valu)
268
286
 
@@ -330,6 +348,12 @@ class Cpe23Str(s_types.Str):
330
348
  def _normPyStr(self, valu):
331
349
  text = valu.lower()
332
350
  if text.startswith('cpe:2.3:'):
351
+
352
+ # Validate the CPE 2.3 string immediately
353
+ if not isValidCpe23(text):
354
+ mesg = 'CPE 2.3 string appears to be invalid.'
355
+ raise s_exc.BadTypeValu(mesg=mesg, valu=valu)
356
+
333
357
  parts = cpesplit(text[8:])
334
358
  if len(parts) > 11:
335
359
  mesg = f'CPE 2.3 string has {len(parts)} fields, expected up to 11.'
@@ -346,6 +370,10 @@ class Cpe23Str(s_types.Str):
346
370
  v2_2[idx] = ''
347
371
  continue
348
372
 
373
+ if idx in (PART_IDX_PART, PART_IDX_LANG) and part == '-':
374
+ v2_2[idx] = ''
375
+ continue
376
+
349
377
  part = fsb_unescape(part)
350
378
  v2_2[idx] = uri_quote(part)
351
379
 
@@ -357,12 +385,22 @@ class Cpe23Str(s_types.Str):
357
385
  v2_2[PART_IDX_OTHER]
358
386
  )
359
387
 
360
- v2_2 = v2_2[:7]
388
+ v2_2 = zipCpe22(v2_2[:7])
389
+
390
+ # Now validate the downconvert
391
+ if not isValidCpe22(v2_2): # pragma: no cover
392
+ mesg = 'Invalid CPE 2.3 to CPE 2.2 conversion.'
393
+ raise s_exc.BadTypeValu(mesg=mesg, valu=valu, v2_2=v2_2)
361
394
 
362
395
  parts = [fsb_unescape(k) for k in parts]
363
396
 
364
397
  elif text.startswith('cpe:/'):
365
398
 
399
+ # Validate the CPE 2.2 string immediately
400
+ if not isValidCpe22(text):
401
+ mesg = 'CPE 2.2 string appears to be invalid.'
402
+ raise s_exc.BadTypeValu(mesg=mesg, valu=valu)
403
+
366
404
  v2_2 = text
367
405
  # automatically normalize CPE 2.2 format to CPE 2.3
368
406
  parts = chopCpe22(text)
@@ -408,24 +446,15 @@ class Cpe23Str(s_types.Str):
408
446
 
409
447
  v2_3 = 'cpe:2.3:' + ':'.join(escaped)
410
448
 
449
+ # Now validate the upconvert
450
+ if not isValidCpe23(v2_3): # pragma: no cover
451
+ mesg = 'Invalid CPE 2.2 to CPE 2.3 conversion.'
452
+ raise s_exc.BadTypeValu(mesg=mesg, valu=valu, v2_3=v2_3)
453
+
411
454
  else:
412
455
  mesg = 'CPE 2.3 string is expected to start with "cpe:2.3:"'
413
456
  raise s_exc.BadTypeValu(valu=valu, mesg=mesg)
414
457
 
415
- rgx = cpe23_regex.match(v2_3)
416
- if rgx is None or rgx.group() != v2_3:
417
- mesg = 'CPE 2.3 string appears to be invalid.'
418
- raise s_exc.BadTypeValu(mesg=mesg, valu=valu)
419
-
420
- if isinstance(v2_2, list):
421
- cpe22 = zipCpe22(v2_2)
422
- else:
423
- cpe22 = v2_2
424
-
425
- rgx = cpe22_regex.match(cpe22)
426
- if rgx is None or rgx.group() != cpe22:
427
- v2_2 = None
428
-
429
458
  subs = {
430
459
  'part': parts[PART_IDX_PART],
431
460
  'vendor': parts[PART_IDX_VENDOR],
@@ -438,11 +467,9 @@ class Cpe23Str(s_types.Str):
438
467
  'target_sw': parts[PART_IDX_TARGET_SW],
439
468
  'target_hw': parts[PART_IDX_TARGET_HW],
440
469
  'other': parts[PART_IDX_OTHER],
470
+ 'v2_2': v2_2,
441
471
  }
442
472
 
443
- if v2_2 is not None:
444
- subs['v2_2'] = v2_2
445
-
446
473
  return v2_3, {'subs': subs}
447
474
 
448
475
  class SemVer(s_types.Int):
@@ -3019,6 +3019,7 @@ class CellTest(s_t_utils.SynTest):
3019
3019
  self.eq(node.get('._woot'), 5)
3020
3020
  self.nn(node.getTagProp('test', 'score'), 6)
3021
3021
 
3022
+ self.maxDiff = None
3022
3023
  roles = s_t_utils.deguidify('[{"type": "role", "iden": "e1ef725990aa62ae3c4b98be8736d89f", "name": "all", "rules": [], "authgates": {"46cfde2c1682566602860f8df7d0cc83": {"rules": [[true, ["layer", "read"]]]}, "4d50eb257549436414643a71e057091a": {"rules": [[true, ["view", "read"]]]}}}]')
3023
3024
  users = s_t_utils.deguidify('[{"type": "user", "iden": "a357138db50780b62093a6ce0d057fd8", "name": "root", "rules": [], "roles": [], "admin": true, "email": null, "locked": false, "archived": false, "authgates": {"46cfde2c1682566602860f8df7d0cc83": {"admin": true}, "4d50eb257549436414643a71e057091a": {"admin": true}}}, {"type": "user", "iden": "f77ac6744671a845c27e571071877827", "name": "visi", "rules": [[true, ["cron", "add"]], [true, ["dmon", "add"]], [true, ["trigger", "add"]]], "roles": [{"type": "role", "iden": "e1ef725990aa62ae3c4b98be8736d89f", "name": "all", "rules": [], "authgates": {"46cfde2c1682566602860f8df7d0cc83": {"rules": [[true, ["layer", "read"]]]}, "4d50eb257549436414643a71e057091a": {"rules": [[true, ["view", "read"]]]}}}], "admin": false, "email": null, "locked": false, "archived": false, "authgates": {"f21b7ae79c2dacb89484929a8409e5d8": {"admin": true}, "d7d0380dd4e743e35af31a20d014ed48": {"admin": true}}}]')
3024
3025
  gates = s_t_utils.deguidify('[{"iden": "46cfde2c1682566602860f8df7d0cc83", "type": "layer", "users": [{"iden": "a357138db50780b62093a6ce0d057fd8", "rules": [], "admin": true}], "roles": [{"iden": "e1ef725990aa62ae3c4b98be8736d89f", "rules": [[true, ["layer", "read"]]], "admin": false}]}, {"iden": "d7d0380dd4e743e35af31a20d014ed48", "type": "trigger", "users": [{"iden": "f77ac6744671a845c27e571071877827", "rules": [], "admin": true}], "roles": []}, {"iden": "f21b7ae79c2dacb89484929a8409e5d8", "type": "cronjob", "users": [{"iden": "f77ac6744671a845c27e571071877827", "rules": [], "admin": true}], "roles": []}, {"iden": "4d50eb257549436414643a71e057091a", "type": "view", "users": [{"iden": "a357138db50780b62093a6ce0d057fd8", "rules": [], "admin": true}], "roles": [{"iden": "e1ef725990aa62ae3c4b98be8736d89f", "rules": [[true, ["view", "read"]]], "admin": false}]}, {"iden": "cortex", "type": "cortex", "users": [], "roles": []}]')
@@ -11,6 +11,7 @@ from unittest.mock import patch
11
11
 
12
12
  import synapse.lib.base as s_base
13
13
  import synapse.lib.const as s_const
14
+ import synapse.lib.msgpack as s_msgpack
14
15
  import synapse.lib.lmdbslab as s_lmdbslab
15
16
  import synapse.lib.thisplat as s_thisplat
16
17
 
@@ -1597,6 +1598,35 @@ class LmdbSlabTest(s_t_utils.SynTest):
1597
1598
  subkv2 = subkv1.getSubKeyVal('pref2')
1598
1599
  self.eq(list(subkv2.keys()), ['wow'])
1599
1600
 
1601
+ async def test_lmdbslab_scan_grow(self):
1602
+ with self.getTestDir() as dirn:
1603
+
1604
+ path = os.path.join(dirn, 'test.lmdb')
1605
+
1606
+ mapsize = s_const.kibibyte * 32
1607
+ async with await s_lmdbslab.Slab.anit(path, map_size=mapsize) as slab:
1608
+
1609
+ self.eq(slab.mapsize, mapsize)
1610
+
1611
+ def slabset(key, valu):
1612
+ slab.replace(s_msgpack.en(key), s_msgpack.en(valu))
1613
+
1614
+ def slabitems():
1615
+ for lkey, lval in slab.scanByFull():
1616
+ yield s_msgpack.un(lkey), s_msgpack.un(lval)
1617
+
1618
+ slabset('one', [1, 2, 3])
1619
+ slabset('two', [2, 3, 4])
1620
+
1621
+ seen = set()
1622
+ for key, valu in slabitems():
1623
+ self.notin(key, seen)
1624
+ seen.add(key)
1625
+
1626
+ valu += ('A' * mapsize,)
1627
+ slabset(key, valu)
1628
+
1629
+ self.gt(slab.mapsize, mapsize)
1600
1630
 
1601
1631
  class LmdbSlabMemLockTest(s_t_utils.SynTest):
1602
1632