zexus 1.8.0 → 1.8.2

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.
Files changed (51) hide show
  1. package/README.md +34 -6
  2. package/bin/zexus +12 -2
  3. package/bin/zpics +12 -2
  4. package/bin/zpm +12 -2
  5. package/bin/zx +12 -2
  6. package/bin/zx-deploy +12 -2
  7. package/bin/zx-dev +12 -2
  8. package/bin/zx-run +12 -2
  9. package/package.json +2 -1
  10. package/rust_core/Cargo.lock +603 -0
  11. package/rust_core/Cargo.toml +26 -0
  12. package/rust_core/README.md +15 -0
  13. package/rust_core/pyproject.toml +25 -0
  14. package/rust_core/src/binary_bytecode.rs +543 -0
  15. package/rust_core/src/contract_vm.rs +643 -0
  16. package/rust_core/src/executor.rs +847 -0
  17. package/rust_core/src/hasher.rs +90 -0
  18. package/rust_core/src/lib.rs +71 -0
  19. package/rust_core/src/merkle.rs +128 -0
  20. package/rust_core/src/rust_vm.rs +2313 -0
  21. package/rust_core/src/signature.rs +79 -0
  22. package/rust_core/src/state_adapter.rs +281 -0
  23. package/rust_core/src/validator.rs +116 -0
  24. package/scripts/postinstall.js +204 -21
  25. package/src/zexus/__init__.py +1 -1
  26. package/src/zexus/cli/main.py +1 -1
  27. package/src/zexus/cli/zpm.py +1 -1
  28. package/src/zexus/evaluator/bytecode_compiler.py +150 -52
  29. package/src/zexus/evaluator/core.py +151 -809
  30. package/src/zexus/evaluator/expressions.py +27 -22
  31. package/src/zexus/evaluator/functions.py +171 -126
  32. package/src/zexus/evaluator/statements.py +55 -112
  33. package/src/zexus/module_cache.py +20 -9
  34. package/src/zexus/object.py +330 -38
  35. package/src/zexus/parser/parser.py +103 -23
  36. package/src/zexus/parser/strategy_context.py +318 -6
  37. package/src/zexus/parser/strategy_structural.py +2 -2
  38. package/src/zexus/persistence.py +46 -17
  39. package/src/zexus/security.py +140 -234
  40. package/src/zexus/type_checker.py +44 -5
  41. package/src/zexus/vm/binary_bytecode.py +7 -3
  42. package/src/zexus/vm/bytecode.py +6 -0
  43. package/src/zexus/vm/cache.py +24 -46
  44. package/src/zexus/vm/compiler.py +549 -68
  45. package/src/zexus/vm/memory_pool.py +21 -9
  46. package/src/zexus/vm/vm.py +609 -95
  47. package/src/zexus/zpm/package_manager.py +1 -1
  48. package/src/zexus.egg-info/PKG-INFO +56 -12
  49. package/src/zexus.egg-info/SOURCES.txt +14 -0
  50. package/src/zexus.egg-info/entry_points.txt +5 -1
  51. package/src/zexus.egg-info/requires.txt +26 -0
@@ -17,7 +17,6 @@ Enhanced: File-based persistent caching for faster repeat runs
17
17
 
18
18
  import hashlib
19
19
  import json
20
- import pickle
21
20
  import time
22
21
  from collections import OrderedDict
23
22
  from dataclasses import dataclass
@@ -271,8 +270,9 @@ class BytecodeCache:
271
270
  constants_size = 0
272
271
  for const in bytecode.constants:
273
272
  try:
274
- constants_size += len(pickle.dumps(const))
275
- except (TypeError, pickle.PicklingError):
273
+ import sys as _sys
274
+ constants_size += _sys.getsizeof(const)
275
+ except (TypeError, ValueError):
276
276
  constants_size += 100 # Fallback estimate
277
277
 
278
278
  # Add metadata overhead
@@ -504,9 +504,9 @@ class BytecodeCache:
504
504
  with open(cache_file, 'wb') as f:
505
505
  f.write(data)
506
506
  else:
507
- cache_file = self.cache_dir / f"{key}.cache"
508
- with open(cache_file, 'wb') as f:
509
- pickle.dump(bytecode, f, protocol=pickle.HIGHEST_PROTOCOL)
507
+ # SECURITY (H14): Legacy pickle format disabled — use .zxc only
508
+ if self.debug:
509
+ print(f"⚠️ Cache: Skipping disk save (pickle disabled, .zxc not available)")
510
510
 
511
511
  if self.debug:
512
512
  print(f"💾 Cache: Saved to disk {key[:8]}...")
@@ -531,14 +531,9 @@ class BytecodeCache:
531
531
  print(f"💾 Cache: Loaded .zxc from disk {key[:8]}...")
532
532
  return bytecode
533
533
 
534
- # Fallback to legacy pickle format
535
- cache_file = self.cache_dir / f"{key}.cache"
536
- if cache_file.exists():
537
- with open(cache_file, 'rb') as f:
538
- bytecode = pickle.load(f)
539
- if self.debug:
540
- print(f"💾 Cache: Loaded .cache from disk {key[:8]}...")
541
- return bytecode
534
+ # SECURITY (H14): Legacy pickle .cache format disabled
535
+ # Only .zxc binary format is supported for disk cache
536
+ pass
542
537
  except Exception as e:
543
538
  if self.debug:
544
539
  print(f"⚠️ Cache: Failed to load from disk: {e}")
@@ -713,10 +708,9 @@ class BytecodeCache:
713
708
  f.write(meta_bytes)
714
709
  f.write(bc_bytes)
715
710
  else:
716
- cache_file = self.cache_dir / f"file_{file_key}.cache"
717
- data = {'metadata': meta_dict, 'bytecodes': bytecodes, 'cached_at': time.time()}
718
- with open(cache_file, 'wb') as f:
719
- pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
711
+ # SECURITY (H14): Legacy pickle format disabled
712
+ if self.debug:
713
+ print(f"⚠️ FileCache: Skipping disk save (pickle disabled, .zxc not available)")
720
714
 
721
715
  if self.debug:
722
716
  print(f"💾 FileCache: Saved to disk {file_key[:8]}...")
@@ -749,16 +743,8 @@ class BytecodeCache:
749
743
  bytecodes = _zxc_deserialize_multi(raw[4 + meta_len:])
750
744
  cache_file = zxc_file
751
745
 
752
- # Fallback to legacy pickle
753
- if bytecodes is None:
754
- pkl_file = self.cache_dir / f"file_{file_key}.cache"
755
- if pkl_file.exists():
756
- with open(pkl_file, 'rb') as f:
757
- data = pickle.load(f)
758
- cached_meta = data.get('metadata', {})
759
- bytecodes = data.get('bytecodes', [])
760
- cached_at = data.get('cached_at', time.time())
761
- cache_file = pkl_file
746
+ # SECURITY (H14): Legacy pickle format disabled
747
+ pass
762
748
 
763
749
  if cached_meta is None or bytecodes is None:
764
750
  return None
@@ -810,10 +796,11 @@ class BytecodeCache:
810
796
  return
811
797
 
812
798
  try:
813
- index_file = self.cache_dir / 'file_index.cache'
799
+ # SECURITY (H14): Use JSON instead of pickle for index
800
+ index_file = self.cache_dir / 'file_index.json'
814
801
  if index_file.exists():
815
- with open(index_file, 'rb') as f:
816
- index = pickle.load(f)
802
+ with open(index_file, 'r') as f:
803
+ index = json.load(f)
817
804
  if self.debug:
818
805
  print(f"📂 FileCache: Loaded index with {len(index)} files")
819
806
  except Exception as e:
@@ -826,7 +813,8 @@ class BytecodeCache:
826
813
  return
827
814
 
828
815
  try:
829
- index_file = self.cache_dir / 'file_index.cache'
816
+ # SECURITY (H14): Use JSON instead of pickle for index
817
+ index_file = self.cache_dir / 'file_index.json'
830
818
  # Just save file keys and metadata (not bytecode)
831
819
  index = {
832
820
  key: {
@@ -837,8 +825,8 @@ class BytecodeCache:
837
825
  }
838
826
  for key, data in self._file_cache.items()
839
827
  }
840
- with open(index_file, 'wb') as f:
841
- pickle.dump(index, f, protocol=pickle.HIGHEST_PROTOCOL)
828
+ with open(index_file, 'w') as f:
829
+ json.dump(index, f)
842
830
  except Exception as e:
843
831
  if self.debug:
844
832
  print(f"⚠️ FileCache: Failed to save index: {e}")
@@ -985,18 +973,8 @@ class BytecodeCache:
985
973
  cached.get('content_hash') == metadata.content_hash):
986
974
  return True
987
975
 
988
- # Check disk cache
989
- if self.persistent and self.cache_dir:
990
- cache_file = self.cache_dir / f"file_{file_key}.cache"
991
- if cache_file.exists():
992
- try:
993
- with open(cache_file, 'rb') as f:
994
- data = pickle.load(f)
995
- cached_meta = data.get('metadata', {})
996
- return (cached_meta.get('mtime') == metadata.mtime and
997
- cached_meta.get('content_hash') == metadata.content_hash)
998
- except Exception:
999
- pass
976
+ # SECURITY (H14): Legacy pickle .cache disk cache disabled
977
+ # Only .zxc format is used for disk caching now
1000
978
 
1001
979
  return False
1002
980