parsanol 1.3.130-arm-linux → 1.3.132-arm-linux
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.
- checksums.yaml +4 -4
- data/lib/parsanol/3.2/parsanol_native.so +2 -2
- data/lib/parsanol/3.3/parsanol_native.so +2 -2
- data/lib/parsanol/3.4/parsanol_native.so +2 -2
- data/lib/parsanol/4.0/parsanol_native.so +2 -2
- data/lib/parsanol/native/libparsanol.so +2 -2
- data/lib/parsanol/parg/artifact.rb +36 -4
- data/lib/parsanol/parg/cli.rb +28 -2
- data/lib/parsanol/parg/compiler.rb +40 -4
- data/lib/parsanol/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8a9a959842c1ec95a2e7d65f2e4571468d74006d3a6e0934c652c49d34c2d123
|
|
4
|
+
data.tar.gz: e341531eaff526a3ec332f5acff1dbe26b520c141e343a280ae3aa340f121698
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c5c65ac083e83de4891d1635ab046e09c34d783ef7863d01113c7ef41bbf15ac103df6c768525928366dec353daeb9789fdbbcb84d8040f6abf55dfc915dd04
|
|
7
|
+
data.tar.gz: c8832db22368e9b0715369bee7ddf9a46e19aeddb51217486f509300f84e533ae4e996cfe890eae9fad6a6782fa019ebe57e368daa10436dcefd17548ba41749
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: data/lib/parsanol/3.2/parsanol_native.so
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 40174108 bytes
|
|
4
|
+
sha256: a4abd3f5e778228091e4116065ebb81d15adc599f3482bf9b622737742021ec4
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: data/lib/parsanol/3.3/parsanol_native.so
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 40359356 bytes
|
|
4
|
+
sha256: fbdca2cc15d273d19be06530ec4fa0f3510de1b1279bd8afef9ff9dbf519accc
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: data/lib/parsanol/3.4/parsanol_native.so
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 40353544 bytes
|
|
4
|
+
sha256: e35eba05fd94a28eac6d1251f1be6cd2db12e9b18cad47a211d8b1106edfc743
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: data/lib/parsanol/4.0/parsanol_native.so
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 40363240 bytes
|
|
4
|
+
sha256: 986c052f3c478ec717dbc61f81d11a1210428cf300d9e6c140b23ba68994fe66
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: data/lib/parsanol/native/libparsanol.so
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 36496788 bytes
|
|
4
|
+
sha256: 2bf9b4db07fed268f82cee8074cf77bb08a302ceec53c8bd8f48bfdf00220ae4
|
|
@@ -15,13 +15,15 @@ module Parsanol
|
|
|
15
15
|
attr_reader :envelope, :path, :tables_dir, :imports_dir
|
|
16
16
|
|
|
17
17
|
def self.load(path, tables_dir: nil, imports_dir: nil)
|
|
18
|
-
|
|
18
|
+
text = PARG.read_utf8(path)
|
|
19
|
+
envelope = JSON.parse(text)
|
|
19
20
|
new(envelope, path, tables_dir || File.dirname(path),
|
|
20
|
-
imports_dir: imports_dir)
|
|
21
|
+
imports_dir: imports_dir, raw_text: text)
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def self.from_json(text, tables_dir: nil, imports_dir: nil)
|
|
24
|
-
new(JSON.parse(text), nil, tables_dir, imports_dir: imports_dir
|
|
25
|
+
new(JSON.parse(text), nil, tables_dir, imports_dir: imports_dir,
|
|
26
|
+
raw_text: text)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
SUPPORTED_SHAPE = "parsanol-tree/v2"
|
|
@@ -37,7 +39,7 @@ module Parsanol
|
|
|
37
39
|
2 => 2, "2" => 2, "v2" => 2
|
|
38
40
|
}.freeze
|
|
39
41
|
|
|
40
|
-
def initialize(envelope, path, tables_dir, imports_dir: nil)
|
|
42
|
+
def initialize(envelope, path, tables_dir, imports_dir: nil, raw_text: nil)
|
|
41
43
|
unless envelope["shape"] == SUPPORTED_SHAPE
|
|
42
44
|
raise ArtifactError,
|
|
43
45
|
"unsupported artifact shape #{envelope['shape'].inspect} " \
|
|
@@ -63,6 +65,7 @@ module Parsanol
|
|
|
63
65
|
# sources when the pure-Ruby path recompiles the embedded source;
|
|
64
66
|
# in-memory artifacts (path nil) pass the directory explicitly.
|
|
65
67
|
@imports_dir = imports_dir
|
|
68
|
+
@raw_text = raw_text
|
|
66
69
|
verify_checksum!
|
|
67
70
|
@compiler = nil
|
|
68
71
|
end
|
|
@@ -655,7 +658,16 @@ module Parsanol
|
|
|
655
658
|
@compiled[rule] ||= compiler.atom_for(rule)
|
|
656
659
|
end
|
|
657
660
|
|
|
661
|
+
# Two tiers. FAST: when the bake sealed the file, a zero-hole
|
|
662
|
+
# sha256 over the raw bytes proves byte integrity without parsing
|
|
663
|
+
# semantics — O(bytes), no canonicalization. DEEP: the canonical
|
|
664
|
+
# checksum (cross-engine content equality), which also covers
|
|
665
|
+
# artifacts baked before byte_checksum existed. A sealed artifact
|
|
666
|
+
# loaded with its raw text verifies BOTH; a bare envelope (direct
|
|
667
|
+
# construction) verifies canonical only.
|
|
658
668
|
def verify_checksum!
|
|
669
|
+
verify_byte_checksum! if envelope["byte_checksum"]
|
|
670
|
+
|
|
659
671
|
stored = envelope["checksum"]
|
|
660
672
|
computed = Compiler.checksum(envelope)
|
|
661
673
|
return if stored == computed
|
|
@@ -664,6 +676,26 @@ module Parsanol
|
|
|
664
676
|
"artifact checksum mismatch: stored #{stored.inspect}, " \
|
|
665
677
|
"computed #{computed.inspect}"
|
|
666
678
|
end
|
|
679
|
+
|
|
680
|
+
# The bake computed the digest over the file bytes with the
|
|
681
|
+
# digest's own 64-hex region zeroed (Compiler.seal_json). Any
|
|
682
|
+
# flipped bit anywhere else in the file mismatches — corrupted
|
|
683
|
+
# distribution, wrong file, hand-edited payload: all rejected
|
|
684
|
+
# before any parse work.
|
|
685
|
+
def verify_byte_checksum!
|
|
686
|
+
stored = envelope["byte_checksum"]
|
|
687
|
+
return if stored.nil? || @raw_text.nil?
|
|
688
|
+
|
|
689
|
+
placeholder = Compiler::BYTE_CHECKSUM_PLACEHOLDER
|
|
690
|
+
zeroed = @raw_text.sub(stored.to_s, placeholder)
|
|
691
|
+
computed = "sha256:#{Digest::SHA256.hexdigest(zeroed)}"
|
|
692
|
+
return if stored == computed
|
|
693
|
+
|
|
694
|
+
raise ArtifactError,
|
|
695
|
+
"artifact byte checksum mismatch: stored #{stored.inspect}, " \
|
|
696
|
+
"computed #{computed.inspect} — the file bytes are not the " \
|
|
697
|
+
"sealed bake output"
|
|
698
|
+
end
|
|
667
699
|
end
|
|
668
700
|
end
|
|
669
701
|
end
|
data/lib/parsanol/parg/cli.rb
CHANGED
|
@@ -18,7 +18,11 @@ module Parsanol
|
|
|
18
18
|
usage: parsanol parg <command> <grammar> [arguments]
|
|
19
19
|
|
|
20
20
|
commands:
|
|
21
|
-
compile <file.parg> [-o out.json]
|
|
21
|
+
compile <file.parg> [-o out.json] [--bindings TARGET|all]
|
|
22
|
+
compile to an artifact envelope;
|
|
23
|
+
--bindings also writes one
|
|
24
|
+
checksummed per-target binding
|
|
25
|
+
artifact beside it (#432)
|
|
22
26
|
test <file.parg|artifact.json> run the grammar's test section
|
|
23
27
|
parse <file> [--entry E] INPUT parse one input; prints the tree
|
|
24
28
|
and the bound captures
|
|
@@ -141,11 +145,33 @@ module Parsanol
|
|
|
141
145
|
source = @argv.shift
|
|
142
146
|
out = flag_value("-o") || default_artifact_name(source)
|
|
143
147
|
envelope = compile_source(source).envelope
|
|
144
|
-
|
|
148
|
+
# Seal: the exact text written is the exact text the byte-level
|
|
149
|
+
# checksum covers (Compiler.seal_json includes the trailing
|
|
150
|
+
# newline).
|
|
151
|
+
File.write(out, Compiler.seal_json(envelope), encoding: Encoding::UTF_8)
|
|
145
152
|
puts "#{out} #{envelope['checksum']} warnings=#{envelope['lint']['order_warnings'].size}"
|
|
153
|
+
bindings_targets.each do |target|
|
|
154
|
+
# The declared per-target binding artifacts (#432): one
|
|
155
|
+
# checksummed bindings payload per target, written beside the
|
|
156
|
+
# artifact. `--bindings all` expands to the full target set.
|
|
157
|
+
artifact = Artifact.from_json(JSON.generate(envelope))
|
|
158
|
+
path = out.sub(/\.json\z/i, ".bindings.#{target}.json")
|
|
159
|
+
File.write(path, "#{artifact.bindings_artifact_json(target)}\n", encoding: Encoding::UTF_8)
|
|
160
|
+
puts "#{path} #{artifact.bindings_artifact(target).payload['checksum']}"
|
|
161
|
+
end
|
|
146
162
|
0
|
|
147
163
|
end
|
|
148
164
|
|
|
165
|
+
# Every --bindings flag value, `all` expanded to the target set.
|
|
166
|
+
# Empty when the flag is absent (compile emits no binding artifacts).
|
|
167
|
+
def bindings_targets
|
|
168
|
+
values = []
|
|
169
|
+
while (value = flag_value("--bindings"))
|
|
170
|
+
values.concat(value == "all" ? Bindings::Artifact::TARGETS.dup : [value])
|
|
171
|
+
end
|
|
172
|
+
values.uniq
|
|
173
|
+
end
|
|
174
|
+
|
|
149
175
|
# Freshness (parsanol-ruby#209): verify an artifact was compiled
|
|
150
176
|
# from the given source. The stale-shipped-artifact incident class
|
|
151
177
|
# (an old artifact silently taking precedence over the corrected
|
|
@@ -25,19 +25,43 @@ module Parsanol
|
|
|
25
25
|
new(document, tables_dir).compile
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
# Canonical checksum over an envelope (everything except the
|
|
29
|
-
# itself
|
|
28
|
+
# Canonical checksum over an envelope (everything except the
|
|
29
|
+
# checksum itself and the byte-level checksum — the byte digest
|
|
30
|
+
# attests the FILE serialization, which is producer-specific and
|
|
31
|
+
# must never enter the cross-engine canonical payload). Used both
|
|
32
|
+
# when building an artifact and when verifying one.
|
|
30
33
|
def self.checksum(envelope)
|
|
31
|
-
payload = envelope.except("checksum")
|
|
34
|
+
payload = envelope.except("checksum", "byte_checksum")
|
|
32
35
|
"sha256:#{Digest::SHA256.hexdigest(JSON.generate(canonicalize(payload)))}"
|
|
33
36
|
end
|
|
34
37
|
|
|
38
|
+
# The byte-level checksum's placeholder: a fixed-width zero region,
|
|
39
|
+
# so the sealed bytes and the verification bytes differ only inside
|
|
40
|
+
# that region (sha256 hex is 64 chars — same width).
|
|
41
|
+
BYTE_CHECKSUM_PLACEHOLDER = ("0" * 64).freeze
|
|
42
|
+
BYTE_CHECKSUM_TRAILING = "\n"
|
|
43
|
+
|
|
44
|
+
# Seal an envelope for writing: stamp the byte-level checksum over
|
|
45
|
+
# the exact file bytes (the final serialization with a trailing
|
|
46
|
+
# newline and the digest's own region zeroed) and return the exact
|
|
47
|
+
# text to write. No sidecar — the integrity travels inside the
|
|
48
|
+
# artifact. The canonical `checksum` is untouched: it attests
|
|
49
|
+
# content, `byte_checksum` attests bytes.
|
|
50
|
+
def self.seal_json(envelope)
|
|
51
|
+
sealed = envelope.merge("byte_checksum" => BYTE_CHECKSUM_PLACEHOLDER)
|
|
52
|
+
text = JSON.generate(sealed) + BYTE_CHECKSUM_TRAILING
|
|
53
|
+
digest = Digest::SHA256.hexdigest(text)
|
|
54
|
+
sealed["byte_checksum"] = "sha256:#{digest}"
|
|
55
|
+
JSON.generate(sealed) + BYTE_CHECKSUM_TRAILING
|
|
56
|
+
end
|
|
57
|
+
|
|
35
58
|
# Producer metadata: the checksum pins the exact producer, but the
|
|
36
59
|
# semantics hash (ruby#377) skips these fields so a re-bake by a
|
|
37
60
|
# newer compiler — or a different Ruby patch stamping
|
|
38
61
|
# unicode_tables — is byte-stable when the grammar's behavior is
|
|
39
62
|
# unchanged. Mirrors the cross-engine parity view.
|
|
40
|
-
SEMANTICS_EXCLUDED = %w[checksum compiler_version
|
|
63
|
+
SEMANTICS_EXCLUDED = %w[checksum byte_checksum compiler_version
|
|
64
|
+
unicode_tables semantics_hash validated].freeze
|
|
41
65
|
|
|
42
66
|
def self.semantics_hash(envelope)
|
|
43
67
|
payload = envelope.except(*SEMANTICS_EXCLUDED)
|
|
@@ -129,6 +153,18 @@ module Parsanol
|
|
|
129
153
|
failures = self.class.self_test(envelope, tables_dir: @tables_dir)
|
|
130
154
|
raise CompileError, failures.join("\n") unless failures.empty?
|
|
131
155
|
|
|
156
|
+
# The validation receipt: what this bake actually checked, inside
|
|
157
|
+
# the envelope the checksums cover. "valid/validated" is then an
|
|
158
|
+
# inspectable field of the artifact, not an out-of-band claim.
|
|
159
|
+
envelope["validated"] = {
|
|
160
|
+
"lint_errors" => 0, # compile raises on lint errors before this
|
|
161
|
+
"lint_warnings" => @envelope_warnings.size,
|
|
162
|
+
"tests_total" => @document.tests.size,
|
|
163
|
+
"tests_failures" => 0, # run_tests raises on failures before this
|
|
164
|
+
"self_test" => Native.available?,
|
|
165
|
+
}
|
|
166
|
+
envelope["checksum"] = Compiler.checksum(envelope)
|
|
167
|
+
|
|
132
168
|
Result.new(@atom_cache, @warnings, envelope)
|
|
133
169
|
end
|
|
134
170
|
|
data/lib/parsanol/version.rb
CHANGED