ppr 0.0.4 → 0.0.8
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 +5 -5
- data/lib/ppr/ppr_core.rb +28 -5
- data/lib/ppr/safer_generator.rb +113 -52
- data/lib/ppr/test_ppr.rb +2 -1
- data/lib/ppr/version.rb +1 -1
- data/ppr.gemspec +3 -3
- metadata +18 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2042d52e7ba854cb3813ded3c053f15f0d62cf72e3a5c62b3b2546d9fc24e12a
|
4
|
+
data.tar.gz: c03dc06cb0f09e56efdae00063e0451389319163b4b674a3d959c22915216dfb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c9c6b98dc45c18bc65a219e7c220b55bfd606d411f1bbcd28ad12bd42cd6271dc224725cb1ad8521e5211f657e3c99627883426252ad5917f9fafd07235113a
|
7
|
+
data.tar.gz: b687e440a1fd675306a070258c0b8807b2725c4a133d05602f9fb7134a1b1073c0a451d63a9f4dc2c07bba151d18ce223bd628cf543c211ccdac7f66de18e018
|
data/lib/ppr/ppr_core.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
require "ppr/safer_generator.rb"
|
6
6
|
require "ppr/keyword_searcher.rb"
|
7
|
+
require 'delegate'
|
7
8
|
|
8
9
|
module Ppr
|
9
10
|
|
@@ -302,11 +303,26 @@ class LoadRequire < Macro
|
|
302
303
|
super("",num,ppr,expand: expand)
|
303
304
|
end
|
304
305
|
|
306
|
+
def set_locations(locations)
|
307
|
+
@locations = locations
|
308
|
+
end
|
309
|
+
|
310
|
+
def find_file(name)
|
311
|
+
@locations.each do |i|
|
312
|
+
filepath = i + "/" + name
|
313
|
+
if File.exist?(filepath)
|
314
|
+
return filepath
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
raise "File #{name} was not found in includes."
|
319
|
+
end
|
320
|
+
|
305
321
|
# Loads and preprocess file +name+.
|
306
322
|
def loadm(name)
|
307
323
|
output = StringIO.new("")
|
308
324
|
# print "name=#{name}\n"
|
309
|
-
File.open(name,"r") do |input|
|
325
|
+
File.open(find_file(name),"r") do |input|
|
310
326
|
@ppr.preprocess(input,output)
|
311
327
|
end
|
312
328
|
return output.string
|
@@ -392,7 +408,8 @@ class Preprocessor
|
|
392
408
|
endm: ".end",
|
393
409
|
expand: ":<",
|
394
410
|
separator: /^|[^\w]|$/, glue: "##",
|
395
|
-
escape: "\\"
|
411
|
+
escape: "\\",
|
412
|
+
includes: Dir.pwd)
|
396
413
|
# Check and Initialize the keywords
|
397
414
|
# NOTE: since there are a lot of checks, use a generic but
|
398
415
|
# harder to read code.
|
@@ -453,6 +470,10 @@ class Preprocessor
|
|
453
470
|
params.each do |k,v|
|
454
471
|
parameter_set(k,v)
|
455
472
|
end
|
473
|
+
|
474
|
+
#include folder locations to search for load and require
|
475
|
+
@includes = []
|
476
|
+
(@includes << includes).flatten!
|
456
477
|
end
|
457
478
|
|
458
479
|
# Methods for handling the execution context of the macros.
|
@@ -531,17 +552,17 @@ class Preprocessor
|
|
531
552
|
|
532
553
|
# Tells if a line corresponds to an end keyword.
|
533
554
|
def is_endm?(line)
|
534
|
-
@endm.match(line)
|
555
|
+
@endm.match(line.strip)
|
535
556
|
end
|
536
557
|
|
537
558
|
# Tells if a line corresponds to an else keyword.
|
538
559
|
def is_elsem?(line)
|
539
|
-
@elsem.match(line)
|
560
|
+
@elsem.match(line.strip)
|
540
561
|
end
|
541
562
|
|
542
563
|
# Tells if a line corresponds to an endif keyword.
|
543
564
|
def is_endifm?(line)
|
544
|
-
@endifm.match(line)
|
565
|
+
@endifm.match(line.strip)
|
545
566
|
end
|
546
567
|
|
547
568
|
# Extract a macro definition from a +line+ if there is one.
|
@@ -606,8 +627,10 @@ class Preprocessor
|
|
606
627
|
macro = Assign.new(name,@number,self,expand: @expand)
|
607
628
|
when @loadm then
|
608
629
|
macro = Load.new(@number,self,expand: @expand)
|
630
|
+
macro.set_locations(@includes)
|
609
631
|
when @requirem then
|
610
632
|
macro = Require.new(@number,self,expand: @expand)
|
633
|
+
macro.set_locations(@includes)
|
611
634
|
when @ifm then
|
612
635
|
macro = If.new(@number,self,expand: @expand)
|
613
636
|
else
|
data/lib/ppr/safer_generator.rb
CHANGED
@@ -43,6 +43,16 @@ class SaferGenerator
|
|
43
43
|
methods = DANGER_METHODS + @black_methods
|
44
44
|
# Gather the constants to strip.
|
45
45
|
constants = DANGER_CONSTANTS + @black_constants
|
46
|
+
# Save the dangerous methods in a private safe.
|
47
|
+
@safe_of_methods = {}
|
48
|
+
methods.each do |meth|
|
49
|
+
@safe_of_methods[meth]=method(meth)
|
50
|
+
end
|
51
|
+
# Save the dangerous constants in a private safe.
|
52
|
+
@safe_of_constants = {}
|
53
|
+
constants.each do |cst|
|
54
|
+
@safe_of_constants[cst] = Object.send(:const_get,cst)
|
55
|
+
end
|
46
56
|
# Strip the dangerous methods.
|
47
57
|
methods.each do |meth|
|
48
58
|
Kernel.send(:undef_method,meth)
|
@@ -53,6 +63,21 @@ class SaferGenerator
|
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
66
|
+
# Restores all the stripped Kernel methods and constants appart from the
|
67
|
+
# elements of the white list.
|
68
|
+
# Also strip Object from dangerous methods and constants apart
|
69
|
+
# from the elements of the white list.
|
70
|
+
def unsecure
|
71
|
+
# Restores the dangerous methods in a private safe.
|
72
|
+
@safe_of_methods.each do |(name,pr)|
|
73
|
+
Kernel.send(:define_method,name,&pr)
|
74
|
+
end
|
75
|
+
# Restors the dangerous constants in a private safe.
|
76
|
+
@safe_of_constants.each do |(name,cst)|
|
77
|
+
Object.const_set(name,cst)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
56
81
|
|
57
82
|
# Executes +block+ in a safe context for generating text into a +stream+.
|
58
83
|
#
|
@@ -65,61 +90,97 @@ class SaferGenerator
|
|
65
90
|
end
|
66
91
|
# Creates the pipe for communicating with the block.
|
67
92
|
rd,wr = IO.pipe
|
68
|
-
# Creates a process for executing the block.
|
69
|
-
pid = fork
|
70
|
-
if pid then
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
else
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
93
|
+
# # Creates a process for executing the block.
|
94
|
+
# pid = fork
|
95
|
+
# if pid then
|
96
|
+
# # This is the parent: waits for the block execution result.
|
97
|
+
# # No need to write on the pipe. close it.
|
98
|
+
# wr.close
|
99
|
+
# # Read the result of the process and send it to stream
|
100
|
+
# until rd.eof?
|
101
|
+
# stream << rd.read
|
102
|
+
# end
|
103
|
+
# # No more need of rd.
|
104
|
+
# rd.close
|
105
|
+
# # Wait the end of the child process
|
106
|
+
# Process.wait(pid)
|
107
|
+
# # Where there a trouble?
|
108
|
+
# unless $?.exited? then
|
109
|
+
# # pid did not exit, internal error.
|
110
|
+
# raise "*Internal error*: safer process #{pid} did not exit."
|
111
|
+
# end
|
112
|
+
# if $?.exitstatus !=0 then
|
113
|
+
# # Reconstruct the exception from the stream, the exit
|
114
|
+
# # status is the number of line to use.
|
115
|
+
# e0 = Marshal.load( stream.string.each_line.
|
116
|
+
# to_a[-$?.exitstatus..-1].join )
|
117
|
+
# # Then resend the eception encapsulated into another one
|
118
|
+
# # telling the safer process failed.
|
119
|
+
# begin
|
120
|
+
# raise e0
|
121
|
+
# rescue Exception => e1
|
122
|
+
# raise SaferException.new("*Error*: exception occured in safer process #{pid}.")
|
123
|
+
# end
|
124
|
+
# end
|
125
|
+
# else
|
126
|
+
# # This is the child: enter in safe mode and execute the block.
|
127
|
+
# # No need to write on the pipe. close it.
|
128
|
+
# rd.close
|
129
|
+
# # Secure.
|
130
|
+
# secure
|
131
|
+
# # Execute the block.
|
132
|
+
# begin
|
133
|
+
# block.call(wr)
|
134
|
+
# rescue Exception => e
|
135
|
+
# # The exception is serialized and passed to the main process
|
136
|
+
# # through the pipe.
|
137
|
+
# e = Marshal.dump(e)
|
138
|
+
# wr << "\n" << e
|
139
|
+
# # The exit status is the number of line of the serialized
|
140
|
+
# # exception.
|
141
|
+
# exit!(e.each_line.count)
|
142
|
+
# end
|
143
|
+
# # No more need of wr.
|
144
|
+
# wr.close
|
145
|
+
# # End the process without any error.
|
146
|
+
# exit!(0)
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# # Is there a string to return?
|
150
|
+
# if to_return then
|
151
|
+
# return stream.string
|
152
|
+
# else
|
153
|
+
# return nil
|
154
|
+
# end
|
155
|
+
|
156
|
+
# Secure.
|
157
|
+
secure
|
158
|
+
trouble = nil
|
159
|
+
# Execute the block.
|
160
|
+
begin
|
161
|
+
block.call(wr)
|
162
|
+
rescue Exception => e
|
163
|
+
trouble = e
|
164
|
+
end
|
165
|
+
# No more need of wr.
|
166
|
+
wr.close
|
167
|
+
|
168
|
+
# Unsecure and process the result.
|
169
|
+
unsecure
|
170
|
+
# Read the result of the process and send it to stream
|
171
|
+
until rd.eof?
|
172
|
+
stream << rd.read
|
173
|
+
end
|
174
|
+
# No more need of rd.
|
175
|
+
rd.close
|
176
|
+
if trouble then
|
107
177
|
begin
|
108
|
-
|
109
|
-
rescue Exception =>
|
110
|
-
|
111
|
-
# through the pipe.
|
112
|
-
e = Marshal.dump(e)
|
113
|
-
wr << "\n" << e
|
114
|
-
# The exit status is the number of line of the serialized
|
115
|
-
# exception.
|
116
|
-
exit!(e.each_line.count)
|
178
|
+
raise trouble
|
179
|
+
rescue Exception => e1
|
180
|
+
raise SaferException.new("*Error*: exception occured in safe mode.")
|
117
181
|
end
|
118
|
-
# No more need of wr.
|
119
|
-
wr.close
|
120
|
-
# End the process without any error.
|
121
|
-
exit!(0)
|
122
182
|
end
|
183
|
+
|
123
184
|
# Is there a string to return?
|
124
185
|
if to_return then
|
125
186
|
return stream.string
|
data/lib/ppr/test_ppr.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
######################################################################
|
4
4
|
|
5
5
|
require "ppr.rb"
|
6
|
+
require 'stringio'
|
6
7
|
|
7
8
|
# Function for testing a preprocessor
|
8
9
|
def test_preprocessor(preprocessor,input,expected)
|
@@ -149,7 +150,7 @@ $success &= test_preprocessor_exception($ppr,
|
|
149
150
|
print "... Undefined symbol in macro code... "
|
150
151
|
$success &= test_preprocessor_exception($ppr,
|
151
152
|
"\n.def HE(name)\n :< foobar \n.end\nHE(Foo)",
|
152
|
-
"HE:5):
|
153
|
+
"HE:5):3: undefined local variable or method")
|
153
154
|
|
154
155
|
|
155
156
|
# puts "\nBuilding a preprocessor with an invalid escape character."
|
data/lib/ppr/version.rb
CHANGED
data/ppr.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
34
34
|
spec.require_paths = ["lib"]
|
35
35
|
|
36
|
-
spec.add_development_dependency "bundler", "
|
37
|
-
spec.add_development_dependency "rake", "
|
38
|
-
spec.add_development_dependency "minitest", "
|
36
|
+
spec.add_development_dependency "bundler", ">= 2.2.10"
|
37
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
38
|
+
spec.add_development_dependency "minitest", ">= 12.3.3"
|
39
39
|
end
|
metadata
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ppr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lovic Gauthier
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.2.10
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.2.10
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 12.3.3
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 12.3.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 12.3.3
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 12.3.3
|
55
55
|
description: |-
|
56
56
|
Preprocessor in Ruby: provides a Ruby class named Rpp which implements a text preprocessor where macros are specified in Ruby language.
|
57
57
|
Usage:
|
@@ -90,7 +90,7 @@ homepage: https://github.com/civol
|
|
90
90
|
licenses:
|
91
91
|
- MIT
|
92
92
|
metadata: {}
|
93
|
-
post_install_message:
|
93
|
+
post_install_message:
|
94
94
|
rdoc_options: []
|
95
95
|
require_paths:
|
96
96
|
- lib
|
@@ -105,9 +105,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
105
|
- !ruby/object:Gem::Version
|
106
106
|
version: '0'
|
107
107
|
requirements: []
|
108
|
-
|
109
|
-
|
110
|
-
signing_key:
|
108
|
+
rubygems_version: 3.0.8
|
109
|
+
signing_key:
|
111
110
|
specification_version: 4
|
112
111
|
summary: 'Preprocessor in Ruby: text preprocessor where macros are specified in Ruby
|
113
112
|
language.'
|