1 | ## oils_failures_allowed: 10
|
2 |
|
3 | # Not disallowed:
|
4 | # setglobal, mutating arguments with setvar
|
5 |
|
6 | #### eval() is a pure function
|
7 | shopt --set ysh:upgrade
|
8 |
|
9 | var pure = ^(
|
10 | const a = 1
|
11 | const b = 2
|
12 | )
|
13 |
|
14 | var d = eval(pure, to_dict=true)
|
15 | pp test_ (d)
|
16 |
|
17 | var impure = ^(seq 3 | wc -l)
|
18 |
|
19 | try {
|
20 | call eval(impure)
|
21 | }
|
22 | #= _error
|
23 | echo impure code=$[_error.code]
|
24 |
|
25 | # Can run impure code after pure code
|
26 | call io->eval(impure)
|
27 |
|
28 | ## STDOUT:
|
29 | (Dict) {"a":1,"b":2}
|
30 | impure code=5
|
31 | 3
|
32 | ## END
|
33 |
|
34 | #### evalExpr() is a pure function
|
35 | shopt --set ysh:upgrade
|
36 |
|
37 | var x = 42
|
38 | var pure = ^[x + 1]
|
39 | echo pure=$[evalExpr(pure)]
|
40 |
|
41 | var impure = ^[x + $(echo 3)]
|
42 | try {
|
43 | echo impure code=$[evalExpr(impure)]
|
44 | }
|
45 | echo impure code=$[_error.code]
|
46 |
|
47 | # Can run impure code after pure code
|
48 | echo impure=$[io->evalExpr(impure)]
|
49 |
|
50 | ## STDOUT:
|
51 | pure=43
|
52 | impure code=5
|
53 | impure=45
|
54 | ## END
|
55 |
|
56 | #### Idiom to handle purity errors from untrusted config files
|
57 |
|
58 | echo "TODO: what's the idiom?"
|
59 |
|
60 | # trap PURE ? Is this like trap ERR?
|
61 | # You can handle these errors
|
62 | #
|
63 | # OILS_CRASH_DUMP_DIR=?
|
64 | #
|
65 | # Or do you need 2 more flags?
|
66 | #
|
67 | # --eval-pure-str 'try { source user-config.ysh }'
|
68 | # --eval-str
|
69 | #
|
70 | # That is a bit annoying?
|
71 | #
|
72 | # --eval pure:foo.hay
|
73 | # --eval-str 'pure:echo hi'
|
74 | # --eval any:foo.hay
|
75 | # --eval-str 'any:echo hi'
|
76 |
|
77 | ## STDOUT:
|
78 | ## END
|
79 |
|
80 | #### Executor: can run user-defined Procs
|
81 | shopt --set ysh:upgrade
|
82 |
|
83 | var g = []
|
84 |
|
85 | proc p-outside {
|
86 | # note: append builtin would be nice
|
87 | call g->append('p-outside')
|
88 | }
|
89 |
|
90 | # The Hay file can call any procs? That seems wrong actually
|
91 | # We want to hide some of them
|
92 |
|
93 | var cmd = ^(
|
94 | p-outside
|
95 |
|
96 | proc p-inside {
|
97 | call g->append('p-inside')
|
98 | }
|
99 | p-inside
|
100 | )
|
101 |
|
102 | call eval(cmd)
|
103 |
|
104 | pp test_ (g)
|
105 |
|
106 | ## STDOUT:
|
107 | (List) ["p-outside","p-inside"]
|
108 | ## END
|
109 |
|
110 | #### Executor: can run Hay (while Hay is hard-coded)
|
111 |
|
112 | shopt --set ysh:upgrade
|
113 |
|
114 | hay define Package/INSTALL
|
115 |
|
116 | var cmd = ^(
|
117 | Package foo {
|
118 | version = '1.1'
|
119 | INSTALL { echo hi }
|
120 | }
|
121 | )
|
122 |
|
123 | call eval(cmd)
|
124 |
|
125 | json write (_hay().children[0].attrs)
|
126 |
|
127 | ## STDOUT:
|
128 | {
|
129 | "version": "1.1"
|
130 | }
|
131 | ## END
|
132 |
|
133 |
|
134 | #### Executor: External Commands not allowed
|
135 |
|
136 | var cmd = ^(seq 3)
|
137 |
|
138 | call io->eval(cmd)
|
139 |
|
140 | call eval(cmd)
|
141 |
|
142 | ## status: 127
|
143 | ## STDOUT:
|
144 | 1
|
145 | 2
|
146 | 3
|
147 | ## END
|
148 |
|
149 |
|
150 | #### Command subs, pipelines not allowed with --eval-pure
|
151 |
|
152 | echo >command-sub.sh 'x=$(echo command sub)'
|
153 | echo >command-sub.ysh 'var x = $(echo command sub)'
|
154 |
|
155 | $SH --eval command-sub.sh -c 'echo $x'
|
156 | $SH --eval-pure command-sub.sh -c 'echo command-sub.sh=$?'
|
157 | $SH --eval-pure command-sub.ysh -c 'echo command-sub.ysh=$?'
|
158 |
|
159 | echo
|
160 |
|
161 | echo >pipeline.sh 'seq 3 | wc -l'
|
162 |
|
163 | $SH --eval pipeline.sh -c 'echo eval'
|
164 | $SH --eval-pure pipeline.sh -c 'echo pipeline.sh=$?'
|
165 |
|
166 |
|
167 | ## status: 0
|
168 | ## STDOUT:
|
169 | command sub
|
170 | command-sub.sh=5
|
171 | command-sub.ysh=5
|
172 |
|
173 | 3
|
174 | eval
|
175 | pipeline.sh=5
|
176 | ## END
|
177 |
|
178 | #### Process subs, subshells not allowed with eval()
|
179 | shopt --set ysh:upgrade
|
180 |
|
181 | var cmd = ^( cat <(echo 1) <(echo 2) )
|
182 | call io->eval(cmd)
|
183 |
|
184 | try {
|
185 | call eval(cmd)
|
186 | }
|
187 | echo code=$[_error.code] message=$[_error.message]
|
188 | echo
|
189 |
|
190 | var cmd = ^(( echo subshell ) )
|
191 | call io->eval(cmd)
|
192 |
|
193 | try {
|
194 | call eval(cmd)
|
195 | }
|
196 | echo code=$[_error.code] message=$[_error.message]
|
197 |
|
198 | ## STDOUT:
|
199 | 1
|
200 | 2
|
201 | code=5 message=Process subs aren't allowed in pure mode (OILS-ERR-204)
|
202 |
|
203 | subshell
|
204 | code=5 message=Subshells aren't allowed in pure mode (OILS-ERR-204)
|
205 | ## END
|
206 |
|
207 | #### Background job &
|
208 | shopt --set ysh:upgrade
|
209 |
|
210 | var cmd = ^( sleep 0.01 & wait )
|
211 | call io->eval(cmd)
|
212 |
|
213 | try {
|
214 | call eval(cmd)
|
215 | }
|
216 | echo code=$[_error.code] message=$[_error.message]
|
217 |
|
218 | var cmd = ^( seq 3 | wc -l )
|
219 | call io->eval(cmd)
|
220 |
|
221 | try {
|
222 | call eval(cmd)
|
223 | }
|
224 | echo code=$[_error.code] message=$[_error.message]
|
225 |
|
226 | ## STDOUT:
|
227 | code=5 message=Background jobs aren't allowed in pure mode (OILS-ERR-204)
|
228 | 3
|
229 | code=5 message=Pipelines aren't allowed in pure mode (OILS-ERR-204)
|
230 | ## END
|
231 |
|
232 | #### Redirects
|
233 | shopt --set ysh:upgrade
|
234 |
|
235 | hay define Package
|
236 | var cmd = ^( Package foo > out.txt )
|
237 | call io->eval(cmd)
|
238 | rm -v out.txt
|
239 |
|
240 | try {
|
241 | call eval(cmd)
|
242 | }
|
243 | # not created, but there's also no error?
|
244 | # oh it's because of the PureExecutor
|
245 |
|
246 | ## STDOUT:
|
247 | TODO
|
248 | ## END
|
249 |
|
250 | #### Are any builtins allowed? true, false
|
251 | shopt --set ysh:upgrade
|
252 |
|
253 |
|
254 | # what other builtins should be allowed?
|
255 | # - set and shopt could be dangerous?
|
256 | # - set -- 1 2 3 may be OK
|
257 | # - test -n is safe, but test --file is not
|
258 | # - YSH mostly won't need it
|
259 | # - not part of YSH
|
260 | # - unset
|
261 | # - printf -v (otherwise printf does I/O)
|
262 | # - shift - use ARGV
|
263 | # - getopts
|
264 | # - alias
|
265 | # Other:
|
266 | # - type - some of this does I/O
|
267 | #
|
268 | # If we only consider YSH, everything has a trivial replacement, e.g. true and
|
269 | # false. false can be assert [false]
|
270 |
|
271 | var cmd = ^(
|
272 | true
|
273 | echo true
|
274 | builtin true
|
275 | echo builtin true
|
276 | command true
|
277 | echo command true
|
278 |
|
279 | builtin false
|
280 | echo builtin false
|
281 | )
|
282 |
|
283 | call io->eval(cmd)
|
284 | call eval(cmd)
|
285 | echo
|
286 |
|
287 | ## STDOUT:
|
288 | true
|
289 | builtin true
|
290 | command true
|
291 | ## END
|
292 |
|
293 | #### Are source or use builtins allowed?
|
294 | shopt --set ysh:upgrade
|
295 |
|
296 | # Problem: they cna "steal" information with directory traversal attacks?
|
297 | # maybe only allow them in the same dirs
|
298 | #
|
299 | # Or maybe have a $PATH - $OILS_LIB_PATH
|
300 | # and it can only be set by the caller, via command line flag?
|
301 | #
|
302 | # ysh --oils-path dir1:dir2 --eval
|
303 | #
|
304 | # use foo.ysh # relative to the path
|
305 |
|
306 | var cmd = ^(
|
307 | source foo.ysh
|
308 | use foo.ysh
|
309 | )
|
310 |
|
311 | call eval (cmd)
|
312 |
|
313 | ## STDOUT:
|
314 | ## END
|
315 |
|
316 | #### Can log to stderr in pure mode
|
317 | shopt --set ysh:upgrade
|
318 |
|
319 | var cmd = ^(
|
320 | var name = 'world'
|
321 |
|
322 | # I think this should be allowed
|
323 | # And maybe log can be customized with:
|
324 | # - xtrace unification? hierarchy
|
325 | # - timestamps
|
326 |
|
327 | log "hi $name"
|
328 | )
|
329 |
|
330 | call io->eval(cmd)
|
331 | call eval (cmd)
|
332 |
|
333 | ## STDOUT:
|
334 | ## END
|
335 |
|
336 |
|
337 | #### io and vm are not allowed
|
338 |
|
339 | var cmd = ^(
|
340 | = vm.getFrame(-1)
|
341 | = vm.id({})
|
342 |
|
343 | = io.stdin
|
344 | )
|
345 |
|
346 | call io->eval(cmd)
|
347 | call eval (cmd)
|
348 |
|
349 | ## STDOUT:
|
350 | ## END
|
351 |
|
352 | #### Can't make an alias of io->eval and call it, etc.
|
353 | shopt --set ysh:upgrade
|
354 |
|
355 | # The --eval-pure could be make an alias, and then "trick" the post-amble into
|
356 | # calling it.
|
357 |
|
358 | var f = io->eval
|
359 |
|
360 | var cmd = ^(echo hi)
|
361 |
|
362 | call f(cmd)
|
363 |
|
364 | ## STDOUT:
|
365 | ## END
|
366 |
|
367 | #### Globbing not allowed
|
368 |
|
369 | # TODO: should be @[io.glob('*.txt')]
|
370 | # That is a bit verbose
|
371 | var cmd = ^(
|
372 | echo *.txt
|
373 | )
|
374 |
|
375 | call io->eval(cmd)
|
376 | call eval(cmd)
|
377 |
|
378 | ## STDOUT:
|
379 | ## END
|
380 |
|
381 | #### $RANDOM $SECONDS
|
382 | shopt --set ysh:upgrade
|
383 |
|
384 | var cmd = ^(
|
385 | echo not-implemented=$RANDOM
|
386 | echo $SECONDS
|
387 | )
|
388 |
|
389 | call io->eval(cmd)
|
390 | call eval(cmd)
|
391 |
|
392 | ## STDOUT:
|
393 | ## END
|
394 |
|
395 | #### Purely-evaluated code can't set traps for later
|
396 |
|
397 | # this follows from 'no builtins', but probably good to test
|
398 |
|
399 | var cmd = ^(
|
400 | trap 'echo INT' INT
|
401 | )
|
402 |
|
403 | call io->eval(cmd)
|
404 | call eval(cmd)
|
405 |
|
406 | ## STDOUT:
|
407 | ## END
|