35
36:- module(sandbox,
37 [ safe_goal/1, 38 safe_call/1 39 ]). 40:- use_module(library(apply_macros),[expand_phrase/2]). 41:- use_module(library(apply),[maplist/2]). 42:- use_module(library(assoc),[empty_assoc/1,get_assoc/3,put_assoc/4]). 43:- use_module(library(debug),[debug/3,debugging/1]). 44:- use_module(library(error),
45 [ must_be/2,
46 instantiation_error/1,
47 type_error/2,
48 permission_error/3
49 ]). 50:- use_module(library(lists),[append/3]). 51:- use_module(library(prolog_format),[format_types/2]). 52
53:- multifile
54 safe_primitive/1, 55 safe_meta_predicate/1, 56 safe_meta/2, 57 safe_meta/3, 58 safe_global_variable/1, 59 safe_directive/1. 60
62
75
76
77:- meta_predicate
78 safe_goal(:),
79 safe_call(0). 80
90
91safe_call(Goal0) :-
92 expand_goal(Goal0, Goal),
93 safe_goal(Goal),
94 call(Goal).
95
117
118safe_goal(M:Goal) :-
119 empty_assoc(Safe0),
120 catch(safe(Goal, M, [], Safe0, _), E, true),
121 !,
122 nb_delete(sandbox_last_error),
123 ( var(E)
124 -> true
125 ; throw(E)
126 ).
127safe_goal(_) :-
128 nb_current(sandbox_last_error, E),
129 !,
130 nb_delete(sandbox_last_error),
131 throw(E).
132safe_goal(G) :-
133 debug(sandbox(fail), 'safe_goal/1 failed for ~p', [G]),
134 throw(error(instantiation_error, sandbox(G, []))).
135
136
140
141safe(V, _, Parents, _, _) :-
142 var(V),
143 !,
144 Error = error(instantiation_error, sandbox(V, Parents)),
145 nb_setval(sandbox_last_error, Error),
146 throw(Error).
147safe(M:G, _, Parents, Safe0, Safe) :-
148 !,
149 must_be(atom, M),
150 must_be(callable, G),
151 known_module(M:G, Parents),
152 ( predicate_property(M:G, imported_from(M2))
153 -> true
154 ; M2 = M
155 ),
156 ( ( safe_primitive(M2:G)
157 ; safe_primitive(G),
158 predicate_property(G, iso)
159 )
160 -> Safe = Safe0
161 ; ( predicate_property(M:G, exported)
162 ; predicate_property(M:G, public)
163 ; predicate_property(M:G, multifile)
164 ; predicate_property(M:G, iso)
165 ; memberchk(M:_, Parents)
166 )
167 -> safe(G, M, Parents, Safe0, Safe)
168 ; throw(error(permission_error(call, sandboxed, M:G),
169 sandbox(M:G, Parents)))
170 ).
171safe(G, _, Parents, _, _) :-
172 debugging(sandbox(show)),
173 length(Parents, Level),
174 debug(sandbox(show), '[~D] SAFE ~q?', [Level, G]),
175 fail.
176safe(G, _, Parents, Safe, Safe) :-
177 catch(safe_primitive(G),
178 error(instantiation_error, _),
179 rethrow_instantition_error([G|Parents])),
180 predicate_property(G, iso),
181 !.
182safe(G, M, Parents, Safe, Safe) :-
183 known_module(M:G, Parents),
184 ( predicate_property(M:G, imported_from(M2))
185 -> true
186 ; M2 = M
187 ),
188 ( catch(safe_primitive(M2:G),
189 error(instantiation_error, _),
190 rethrow_instantition_error([M2:G|Parents]))
191 ; predicate_property(M2:G, number_of_rules(0))
192 ),
193 !.
194safe(G, M, Parents, Safe0, Safe) :-
195 predicate_property(G, iso),
196 safe_meta_call(G, M, Called),
197 !,
198 add_iso_parent(G, Parents, Parents1),
199 safe_list(Called, M, Parents1, Safe0, Safe).
200safe(G, M, Parents, Safe0, Safe) :-
201 ( predicate_property(M:G, imported_from(M2))
202 -> true
203 ; M2 = M
204 ),
205 safe_meta_call(M2:G, M, Called),
206 !,
207 safe_list(Called, M, Parents, Safe0, Safe).
208safe(G, M, Parents, Safe0, Safe) :-
209 goal_id(M:G, Id, Gen),
210 ( get_assoc(Id, Safe0, _)
211 -> Safe = Safe0
212 ; put_assoc(Id, Safe0, true, Safe1),
213 ( Gen == M:G
214 -> safe_clauses(Gen, M, [Id|Parents], Safe1, Safe)
215 ; catch(safe_clauses(Gen, M, [Id|Parents], Safe1, Safe),
216 error(instantiation_error, Ctx),
217 unsafe(Parents, Ctx))
218 )
219 ),
220 !.
221safe(G, M, Parents, _, _) :-
222 debug(sandbox(fail),
223 'safe/1 failed for ~p (parents:~p)', [M:G, Parents]),
224 fail.
225
226unsafe(Parents, Var) :-
227 var(Var),
228 !,
229 nb_setval(sandbox_last_error,
230 error(instantiation_error, sandbox(_, Parents))),
231 fail.
232unsafe(_Parents, Ctx) :-
233 Ctx = sandbox(_,_),
234 nb_setval(sandbox_last_error,
235 error(instantiation_error, Ctx)),
236 fail.
237
238rethrow_instantition_error(Parents) :-
239 throw(error(instantiation_error, sandbox(_, Parents))).
240
241safe_clauses(G, M, Parents, Safe0, Safe) :-
242 predicate_property(M:G, interpreted),
243 def_module(M:G, MD:QG),
244 \+ compiled(MD:QG),
245 !,
246 findall(Ref-Body, clause(MD:QG, Body, Ref), Bodies),
247 safe_bodies(Bodies, MD, Parents, Safe0, Safe).
248safe_clauses(G, M, [_|Parents], _, _) :-
249 predicate_property(M:G, visible),
250 !,
251 throw(error(permission_error(call, sandboxed, G),
252 sandbox(M:G, Parents))).
253safe_clauses(_, _, [G|Parents], _, _) :-
254 throw(error(existence_error(procedure, G),
255 sandbox(G, Parents))).
256
257compiled(system:(@(_,_))).
258
259known_module(M:_, _) :-
260 current_module(M),
261 !.
262known_module(M:G, Parents) :-
263 throw(error(permission_error(call, sandboxed, M:G),
264 sandbox(M:G, Parents))).
265
266add_iso_parent(G, Parents, Parents) :-
267 is_control(G),
268 !.
269add_iso_parent(G, Parents, [G|Parents]).
270
271is_control((_,_)).
272is_control((_;_)).
273is_control((_->_)).
274is_control((_*->_)).
275is_control(\+(_)).
276
277
283
284safe_bodies([], _, _, Safe, Safe).
285safe_bodies([Ref-H|T], M, Parents, Safe0, Safe) :-
286 ( H = M2:H2, nonvar(M2),
287 clause_property(Ref, module(M2))
288 -> copy_term(H2, H3),
289 CM = M2
290 ; copy_term(H, H3),
291 CM = M
292 ),
293 safe(H3, CM, Parents, Safe0, Safe1),
294 safe_bodies(T, M, Parents, Safe1, Safe).
295
296def_module(M:G, MD:QG) :-
297 predicate_property(M:G, imported_from(MD)),
298 !,
299 meta_qualify(MD:G, M, QG).
300def_module(M:G, M:QG) :-
301 meta_qualify(M:G, M, QG).
302
308
309safe_list([], _, _, Safe, Safe).
310safe_list([H|T], M, Parents, Safe0, Safe) :-
311 ( H = M2:H2,
312 M == M2 313 -> copy_term(H2, H3)
314 ; copy_term(H, H3) 315 ),
316 safe(H3, M, Parents, Safe0, Safe1),
317 safe_list(T, M, Parents, Safe1, Safe).
318
322
323meta_qualify(MD:G, M, QG) :-
324 predicate_property(MD:G, meta_predicate(Head)),
325 !,
326 G =.. [Name|Args],
327 Head =.. [_|Q],
328 qualify_args(Q, M, Args, QArgs),
329 QG =.. [Name|QArgs].
330meta_qualify(_:G, _, G).
331
332qualify_args([], _, [], []).
333qualify_args([H|T], M, [A|AT], [Q|QT]) :-
334 qualify_arg(H, M, A, Q),
335 qualify_args(T, M, AT, QT).
336
337qualify_arg(S, M, A, Q) :-
338 q_arg(S),
339 !,
340 qualify(A, M, Q).
341qualify_arg(_, _, A, A).
342
343q_arg(I) :- integer(I), !.
344q_arg(:).
345q_arg(^).
346q_arg(//).
347
348qualify(A, M, MZ:Q) :-
349 strip_module(M:A, MZ, Q).
350
360
361goal_id(M:Goal, M:Id, Gen) :-
362 !,
363 goal_id(Goal, Id, Gen).
364goal_id(Var, _, _) :-
365 var(Var),
366 !,
367 instantiation_error(Var).
368goal_id(Atom, Atom, Atom) :-
369 atom(Atom),
370 !.
371goal_id(Term, _, _) :-
372 \+ compound(Term),
373 !,
374 type_error(callable, Term).
375goal_id(Term, Skolem, Gen) :- 376 compound_name_arity(Term, Name, Arity),
377 compound_name_arity(Skolem, Name, Arity),
378 compound_name_arity(Gen, Name, Arity),
379 copy_goal_args(1, Term, Skolem, Gen),
380 ( Gen =@= Term
381 -> ! 382 ; true
383 ),
384 numbervars(Skolem, 0, _).
385goal_id(Term, Skolem, Term) :- 386 debug(sandbox(specify), 'Retrying with ~p', [Term]),
387 copy_term(Term, Skolem),
388 numbervars(Skolem, 0, _).
389
394
395copy_goal_args(I, Term, Skolem, Gen) :-
396 arg(I, Term, TA),
397 !,
398 arg(I, Skolem, SA),
399 arg(I, Gen, GA),
400 copy_goal_arg(TA, SA, GA),
401 I2 is I + 1,
402 copy_goal_args(I2, Term, Skolem, Gen).
403copy_goal_args(_, _, _, _).
404
405copy_goal_arg(Arg, SArg, Arg) :-
406 copy_goal_arg(Arg),
407 !,
408 copy_term(Arg, SArg).
409copy_goal_arg(_, _, _).
410
411copy_goal_arg(Var) :- var(Var), !, fail.
412copy_goal_arg(_:_).
413
423
424term_expansion(safe_primitive(Goal), Term) :-
425 ( verify_safe_declaration(Goal)
426 -> Term = safe_primitive(Goal)
427 ; Term = []
428 ).
429
430system:term_expansion(sandbox:safe_primitive(Goal), Term) :-
431 \+ current_prolog_flag(xref, true),
432 ( verify_safe_declaration(Goal)
433 -> Term = sandbox:safe_primitive(Goal)
434 ; Term = []
435 ).
436
437verify_safe_declaration(Var) :-
438 var(Var),
439 !,
440 instantiation_error(Var).
441verify_safe_declaration(Module:Goal) :-
442 !,
443 must_be(atom, Module),
444 must_be(callable, Goal),
445 ( ok_meta(Module:Goal)
446 -> true
447 ; ( predicate_property(Module:Goal, visible)
448 -> true
449 ; predicate_property(Module:Goal, foreign)
450 ),
451 \+ predicate_property(Module:Goal, imported_from(_)),
452 \+ predicate_property(Module:Goal, meta_predicate(_))
453 -> true
454 ; permission_error(declare, safe_goal, Module:Goal)
455 ).
456verify_safe_declaration(Goal) :-
457 must_be(callable, Goal),
458 ( predicate_property(system:Goal, iso),
459 \+ predicate_property(system:Goal, meta_predicate())
460 -> true
461 ; permission_error(declare, safe_goal, Goal)
462 ).
463
464ok_meta(system:assert(_)).
465ok_meta(system:load_files(_,_)).
466ok_meta(system:use_module(_,_)).
467ok_meta(system:use_module(_)).
468
469verify_predefined_safe_declarations :-
470 forall(clause(safe_primitive(Goal), _Body, Ref),
471 ( catch(verify_safe_declaration(Goal), E, true),
472 ( nonvar(E)
473 -> clause_property(Ref, file(File)),
474 clause_property(Ref, line_count(Line)),
475 print_message(error, bad_safe_declaration(Goal, File, Line))
476 ; true
477 )
478 )).
479
480:- initialization(verify_predefined_safe_declarations, now). 481
493
495
496safe_primitive(true).
497safe_primitive(fail).
498safe_primitive(system:false).
499safe_primitive(repeat).
500safe_primitive(!).
501 502safe_primitive(var(_)).
503safe_primitive(nonvar(_)).
504safe_primitive(system:attvar(_)).
505safe_primitive(integer(_)).
506safe_primitive(float(_)).
507safe_primitive(system:rational(_)).
508safe_primitive(number(_)).
509safe_primitive(atom(_)).
510safe_primitive(system:blob(_,_)).
511safe_primitive(system:string(_)).
512safe_primitive(atomic(_)).
513safe_primitive(compound(_)).
514safe_primitive(callable(_)).
515safe_primitive(ground(_)).
516safe_primitive(system:nonground(_,_)).
517safe_primitive(system:cyclic_term(_)).
518safe_primitive(acyclic_term(_)).
519safe_primitive(system:is_stream(_)).
520safe_primitive(system:'$is_char'(_)).
521safe_primitive(system:'$is_char_code'(_)).
522safe_primitive(system:'$is_char_list'(_,_)).
523safe_primitive(system:'$is_code_list'(_,_)).
524 525safe_primitive(@>(_,_)).
526safe_primitive(@>=(_,_)).
527safe_primitive(==(_,_)).
528safe_primitive(@<(_,_)).
529safe_primitive(@=<(_,_)).
530safe_primitive(compare(_,_,_)).
531safe_primitive(sort(_,_)).
532safe_primitive(keysort(_,_)).
533safe_primitive(system: =@=(_,_)).
534safe_primitive(system:'$btree_find_node'(_,_,_,_,_)).
535
536 537safe_primitive(=(_,_)).
538safe_primitive(\=(_,_)).
539safe_primitive(system:'?='(_,_)).
540safe_primitive(system:unifiable(_,_,_)).
541safe_primitive(unify_with_occurs_check(_,_)).
542safe_primitive(\==(_,_)).
543 544safe_primitive(is(_,_)).
545safe_primitive(>(_,_)).
546safe_primitive(>=(_,_)).
547safe_primitive(=:=(_,_)).
548safe_primitive(=\=(_,_)).
549safe_primitive(=<(_,_)).
550safe_primitive(<(_,_)).
551:- if(current_prolog_flag(bounded, false)). 552safe_primitive(system:nth_integer_root_and_remainder(_,_,_,_)).
553:- endif. 554
555 556safe_primitive(arg(_,_,_)).
557safe_primitive(system:setarg(_,_,_)).
558safe_primitive(system:nb_setarg(_,_,_)).
559safe_primitive(system:nb_linkarg(_,_,_)).
560safe_primitive(functor(_,_,_)).
561safe_primitive(_ =.. _).
562safe_primitive(system:compound_name_arity(_,_,_)).
563safe_primitive(system:compound_name_arguments(_,_,_)).
564safe_primitive(system:'$filled_array'(_,_,_,_)).
565safe_primitive(copy_term(_,_)).
566safe_primitive(system:duplicate_term(_,_)).
567safe_primitive(system:copy_term_nat(_,_)).
568safe_primitive(system:size_abstract_term(_,_,_)).
569safe_primitive(numbervars(_,_,_)).
570safe_primitive(system:numbervars(_,_,_,_)).
571safe_primitive(subsumes_term(_,_)).
572safe_primitive(system:term_hash(_,_)).
573safe_primitive(system:term_hash(_,_,_,_)).
574safe_primitive(system:variant_sha1(_,_)).
575safe_primitive(system:variant_hash(_,_)).
576safe_primitive(system:'$term_size'(_,_,_)).
577
578 579safe_primitive(system:is_dict(_)).
580safe_primitive(system:is_dict(_,_)).
581safe_primitive(system:get_dict(_,_,_)).
582safe_primitive(system:get_dict(_,_,_,_,_)).
583safe_primitive(system:'$get_dict_ex'(_,_,_)).
584safe_primitive(system:dict_create(_,_,_)).
585safe_primitive(system:dict_pairs(_,_,_)).
586safe_primitive(system:put_dict(_,_,_)).
587safe_primitive(system:put_dict(_,_,_,_)).
588safe_primitive(system:del_dict(_,_,_,_)).
589safe_primitive(system:select_dict(_,_,_)).
590safe_primitive(system:b_set_dict(_,_,_)).
591safe_primitive(system:nb_set_dict(_,_,_)).
592safe_primitive(system:nb_link_dict(_,_,_)).
593safe_primitive(system:(:<(_,_))).
594safe_primitive(system:(>:<(_,_))).
595 596safe_primitive(atom_chars(_, _)).
597safe_primitive(atom_codes(_, _)).
598safe_primitive(sub_atom(_,_,_,_,_)).
599safe_primitive(atom_concat(_,_,_)).
600safe_primitive(atom_length(_,_)).
601safe_primitive(char_code(_,_)).
602safe_primitive(system:name(_,_)).
603safe_primitive(system:atomic_concat(_,_,_)).
604safe_primitive(system:atomic_list_concat(_,_)).
605safe_primitive(system:atomic_list_concat(_,_,_)).
606safe_primitive(system:downcase_atom(_,_)).
607safe_primitive(system:upcase_atom(_,_)).
608safe_primitive(system:char_type(_,_)).
609safe_primitive(system:normalize_space(_,_)).
610safe_primitive(system:sub_atom_icasechk(_,_,_)).
611 612safe_primitive(number_codes(_,_)).
613safe_primitive(number_chars(_,_)).
614safe_primitive(system:atom_number(_,_)).
615safe_primitive(system:code_type(_,_)).
616 617safe_primitive(system:atom_string(_,_)).
618safe_primitive(system:number_string(_,_)).
619safe_primitive(system:string_chars(_, _)).
620safe_primitive(system:string_codes(_, _)).
621safe_primitive(system:string_code(_,_,_)).
622safe_primitive(system:sub_string(_,_,_,_,_)).
623safe_primitive(system:split_string(_,_,_,_)).
624safe_primitive(system:atomics_to_string(_,_,_)).
625safe_primitive(system:atomics_to_string(_,_)).
626safe_primitive(system:string_concat(_,_,_)).
627safe_primitive(system:string_length(_,_)).
628safe_primitive(system:string_lower(_,_)).
629safe_primitive(system:string_upper(_,_)).
630safe_primitive(system:term_string(_,_)).
631safe_primitive('$syspreds':term_string(_,_,_)).
632 633safe_primitive(length(_,_)).
634 635safe_primitive(throw(_)).
636safe_primitive(system:abort).
637 638safe_primitive(current_prolog_flag(_,_)).
639safe_primitive(current_op(_,_,_)).
640safe_primitive(system:sleep(_)).
641safe_primitive(system:thread_self(_)).
642safe_primitive(system:get_time(_)).
643safe_primitive(system:statistics(_,_)).
644safe_primitive(system:thread_statistics(Id,_,_)) :-
645 ( var(Id)
646 -> instantiation_error(Id)
647 ; thread_self(Id)
648 ).
649safe_primitive(system:thread_property(Id,_)) :-
650 ( var(Id)
651 -> instantiation_error(Id)
652 ; thread_self(Id)
653 ).
654safe_primitive(system:format_time(_,_,_)).
655safe_primitive(system:format_time(_,_,_,_)).
656safe_primitive(system:date_time_stamp(_,_)).
657safe_primitive(system:stamp_date_time(_,_,_)).
658safe_primitive(system:strip_module(_,_,_)).
659safe_primitive('$messages':message_to_string(_,_)).
660safe_primitive(system:import_module(_,_)).
661safe_primitive(system:file_base_name(_,_)).
662safe_primitive(system:file_directory_name(_,_)).
663safe_primitive(system:file_name_extension(_,_,_)).
664
665safe_primitive(clause(H,_)) :- safe_clause(H).
666safe_primitive(asserta(X)) :- safe_assert(X).
667safe_primitive(assertz(X)) :- safe_assert(X).
668safe_primitive(retract(X)) :- safe_assert(X).
669safe_primitive(retractall(X)) :- safe_assert(X).
670
674safe_primitive('$dicts':'.'(_,K,_)) :- atom(K).
675safe_primitive('$dicts':'.'(_,K,_)) :-
676 ( nonvar(K)
677 -> dict_built_in(K)
678 ; instantiation_error(K)
679 ).
680
681dict_built_in(get(_)).
682dict_built_in(put(_)).
683dict_built_in(put(_,_)).
684
687
688safe_primitive(system:false).
689safe_primitive(system:cyclic_term(_)).
690safe_primitive(system:msort(_,_)).
691safe_primitive(system:sort(_,_,_,_)).
692safe_primitive(system:between(_,_,_)).
693safe_primitive(system:succ(_,_)).
694safe_primitive(system:plus(_,_,_)).
695safe_primitive(system:float_class(_,_)).
696safe_primitive(system:term_variables(_,_)).
697safe_primitive(system:term_variables(_,_,_)).
698safe_primitive(system:'$term_size'(_,_,_)).
699safe_primitive(system:atom_to_term(_,_,_)).
700safe_primitive(system:term_to_atom(_,_)).
701safe_primitive(system:atomic_list_concat(_,_,_)).
702safe_primitive(system:atomic_list_concat(_,_)).
703safe_primitive(system:downcase_atom(_,_)).
704safe_primitive(system:upcase_atom(_,_)).
705safe_primitive(system:is_list(_)).
706safe_primitive(system:memberchk(_,_)).
707safe_primitive(system:'$skip_list'(_,_,_)).
708 709safe_primitive(system:get_attr(_,_,_)).
710safe_primitive(system:get_attrs(_,_)).
711safe_primitive(system:term_attvars(_,_)).
712safe_primitive(system:del_attr(_,_)).
713safe_primitive(system:del_attrs(_)).
714safe_primitive('$attvar':copy_term(_,_,_)).
715 716safe_primitive(system:b_getval(_,_)).
717safe_primitive(system:b_setval(Var,_)) :-
718 safe_global_var(Var).
719safe_primitive(system:nb_getval(_,_)).
720safe_primitive('$syspreds':nb_setval(Var,_)) :-
721 safe_global_var(Var).
722safe_primitive(system:nb_linkval(Var,_)) :-
723 safe_global_var(Var).
724safe_primitive(system:nb_current(_,_)).
725 726safe_primitive(system:assert(X)) :-
727 safe_assert(X).
728 729safe_primitive(system:writeln(_)).
730safe_primitive('$messages':print_message(_,_)).
731
732 733safe_primitive('$syspreds':set_prolog_stack(Stack, limit(ByteExpr))) :-
734 nonvar(Stack),
735 stack_name(Stack),
736 catch(Bytes is ByteExpr, _, fail),
737 prolog_stack_property(Stack, limit(Current)),
738 Bytes =< Current.
739
740stack_name(global).
741stack_name(local).
742stack_name(trail).
743
744safe_primitive('$tabling':abolish_all_tables).
745safe_primitive('$tabling':'$wrap_tabled'(Module:_Head, _Mode)) :-
746 prolog_load_context(module, Module),
747 !.
748safe_primitive('$tabling':'$moded_wrap_tabled'(Module:_Head,_,_,_)) :-
749 prolog_load_context(module, Module),
750 !.
751
752
755
756safe_primitive(system:use_module(Spec, _Import)) :-
757 safe_primitive(system:use_module(Spec)).
758safe_primitive(system:load_files(Spec, Options)) :-
759 safe_primitive(system:use_module(Spec)),
760 maplist(safe_load_file_option, Options).
761safe_primitive(system:use_module(Spec)) :-
762 ground(Spec),
763 ( atom(Spec)
764 -> Path = Spec
765 ; Spec =.. [_Alias, Segments],
766 phrase(segments_to_path(Segments), List),
767 atomic_list_concat(List, Path)
768 ),
769 \+ is_absolute_file_name(Path),
770 \+ sub_atom(Path, _, _, _, '/../'),
771 absolute_file_name(Spec, AbsFile,
772 [ access(read),
773 file_type(prolog),
774 file_errors(fail)
775 ]),
776 file_name_extension(_, Ext, AbsFile),
777 save_extension(Ext).
778
781
782segments_to_path(A/B) -->
783 !,
784 segments_to_path(A),
785 [/],
786 segments_to_path(B).
787segments_to_path(X) -->
788 [X].
789
790save_extension(pl).
791
792safe_load_file_option(if(changed)).
793safe_load_file_option(if(not_loaded)).
794safe_load_file_option(must_be_module(_)).
795safe_load_file_option(optimise(_)).
796safe_load_file_option(silent(_)).
797
804
805safe_assert(C) :- cyclic_term(C), !, fail.
806safe_assert(X) :- var(X), !, fail.
807safe_assert(_Head:-_Body) :- !, fail.
808safe_assert(_:_) :- !, fail.
809safe_assert(_).
810
816
817safe_clause(H) :- var(H), !.
818safe_clause(_:_) :- !, fail.
819safe_clause(_).
820
821
826
827safe_global_var(Name) :-
828 var(Name),
829 !,
830 instantiation_error(Name).
831safe_global_var(Name) :-
832 safe_global_variable(Name).
833
837
838
843
844safe_meta(system:put_attr(V,M,A), Called) :-
845 !,
846 ( atom(M)
847 -> attr_hook_predicates([ attr_unify_hook(A, _),
848 attribute_goals(V,_,_),
849 project_attributes(_,_)
850 ], M, Called)
851 ; instantiation_error(M)
852 ).
853safe_meta(system:with_output_to(Output, G), [G]) :-
854 safe_output(Output),
855 !.
856safe_meta(system:format(Format, Args), Calls) :-
857 format_calls(Format, Args, Calls).
858safe_meta(system:format(Output, Format, Args), Calls) :-
859 safe_output(Output),
860 format_calls(Format, Args, Calls).
861safe_meta(prolog_debug:debug(_Term, Format, Args), Calls) :-
862 format_calls(Format, Args, Calls).
863safe_meta(system:set_prolog_flag(Flag, Value), []) :-
864 atom(Flag),
865 safe_prolog_flag(Flag, Value).
866safe_meta('$attvar':freeze(_Var,Goal), [Goal]).
867safe_meta(phrase(NT,Xs0,Xs), [Goal]) :- 868 expand_nt(NT,Xs0,Xs,Goal).
869safe_meta(phrase(NT,Xs0), [Goal]) :-
870 expand_nt(NT,Xs0,[],Goal).
871safe_meta('$dcg':call_dcg(NT,Xs0,Xs), [Goal]) :-
872 expand_nt(NT,Xs0,Xs,Goal).
873safe_meta('$dcg':call_dcg(NT,Xs0), [Goal]) :-
874 expand_nt(NT,Xs0,[],Goal).
875safe_meta('$tabling':abolish_table_subgoals(V), []) :-
876 \+ qualified(V).
877safe_meta('$tabling':current_table(V, _), []) :-
878 \+ qualified(V).
879safe_meta('$tabling':tnot(G), [G]).
880safe_meta('$tabling':not_exists(G), [G]).
881
882qualified(V) :-
883 nonvar(V),
884 V = _:_.
885
893
894attr_hook_predicates([], _, []).
895attr_hook_predicates([H|T], M, Called) :-
896 ( predicate_property(M:H, defined)
897 -> Called = [M:H|Rest]
898 ; Called = Rest
899 ),
900 attr_hook_predicates(T, M, Rest).
901
902
907
908expand_nt(NT, _Xs0, _Xs, _NewGoal) :-
909 strip_module(NT, _, Plain),
910 var(Plain),
911 !,
912 instantiation_error(Plain).
913expand_nt(NT, Xs0, Xs, NewGoal) :-
914 dcg_translate_rule((pseudo_nt --> NT),
915 (pseudo_nt(Xs0c,Xsc) :- NewGoal0)),
916 ( var(Xsc), Xsc \== Xs0c
917 -> Xs = Xsc, NewGoal1 = NewGoal0
918 ; NewGoal1 = (NewGoal0, Xsc = Xs)
919 ),
920 ( var(Xs0c)
921 -> Xs0 = Xs0c,
922 NewGoal = NewGoal1
923 ; NewGoal = ( Xs0 = Xs0c, NewGoal1 )
924 ).
925
930
931safe_meta_call(Goal, _, _Called) :-
932 debug(sandbox(meta), 'Safe meta ~p?', [Goal]),
933 fail.
934safe_meta_call(Goal, Context, Called) :-
935 ( safe_meta(Goal, Called)
936 -> true
937 ; safe_meta(Goal, Context, Called)
938 ),
939 !. 940safe_meta_call(Goal, _, Called) :-
941 Goal = M:Plain,
942 compound(Plain),
943 compound_name_arity(Plain, Name, Arity),
944 safe_meta_predicate(M:Name/Arity),
945 predicate_property(Goal, meta_predicate(Spec)),
946 !,
947 called(Spec, Plain, Called).
948safe_meta_call(M:Goal, _, Called) :-
949 !,
950 generic_goal(Goal, Gen),
951 safe_meta(M:Gen),
952 called(Gen, Goal, Called).
953safe_meta_call(Goal, _, Called) :-
954 generic_goal(Goal, Gen),
955 safe_meta(Gen),
956 called(Gen, Goal, Called).
957
958called(Gen, Goal, Called) :-
959 compound_name_arity(Goal, _, Arity),
960 called(1, Arity, Gen, Goal, Called).
961
962called(I, Arity, Gen, Goal, Called) :-
963 I =< Arity,
964 !,
965 arg(I, Gen, Spec),
966 ( calling_meta_spec(Spec)
967 -> arg(I, Goal, Called0),
968 extend(Spec, Called0, G),
969 Called = [G|Rest]
970 ; Called = Rest
971 ),
972 I2 is I+1,
973 called(I2, Arity, Gen, Goal, Rest).
974called(_, _, _, _, []).
975
976generic_goal(G, Gen) :-
977 functor(G, Name, Arity),
978 functor(Gen, Name, Arity).
979
980calling_meta_spec(V) :- var(V), !, fail.
981calling_meta_spec(I) :- integer(I), !.
982calling_meta_spec(^).
983calling_meta_spec(//).
984
985
986extend(^, G, Plain) :-
987 !,
988 strip_existential(G, Plain).
989extend(//, DCG, Goal) :-
990 !,
991 ( expand_phrase(call_dcg(DCG,_,_), Goal)
992 -> true
993 ; instantiation_error(DCG) 994 ). 995extend(0, G, G) :- !.
996extend(I, M:G0, M:G) :-
997 !,
998 G0 =.. List,
999 length(Extra, I),
1000 append(List, Extra, All),
1001 G =.. All.
1002extend(I, G0, G) :-
1003 G0 =.. List,
1004 length(Extra, I),
1005 append(List, Extra, All),
1006 G =.. All.
1007
1008strip_existential(Var, Var) :-
1009 var(Var),
1010 !.
1011strip_existential(M:G0, M:G) :-
1012 !,
1013 strip_existential(G0, G).
1014strip_existential(_^G0, G) :-
1015 !,
1016 strip_existential(G0, G).
1017strip_existential(G, G).
1018
1020
1021safe_meta((0,0)).
1022safe_meta((0;0)).
1023safe_meta((0->0)).
1024safe_meta(system:(0*->0)).
1025safe_meta(catch(0,*,0)).
1026safe_meta(findall(*,0,*)).
1027safe_meta('$bags':findall(*,0,*,*)).
1028safe_meta(setof(*,^,*)).
1029safe_meta(bagof(*,^,*)).
1030safe_meta('$bags':findnsols(*,*,0,*)).
1031safe_meta('$bags':findnsols(*,*,0,*,*)).
1032safe_meta(system:call_cleanup(0,0)).
1033safe_meta(system:setup_call_cleanup(0,0,0)).
1034safe_meta(system:setup_call_catcher_cleanup(0,0,*,0)).
1035safe_meta('$attvar':call_residue_vars(0,*)).
1036safe_meta('$syspreds':call_with_inference_limit(0,*,*)).
1037safe_meta('$syspreds':call_with_depth_limit(0,*,*)).
1038safe_meta(^(*,0)).
1039safe_meta(\+(0)).
1040safe_meta(call(0)).
1041safe_meta(call(1,*)).
1042safe_meta(call(2,*,*)).
1043safe_meta(call(3,*,*,*)).
1044safe_meta(call(4,*,*,*,*)).
1045safe_meta(call(5,*,*,*,*,*)).
1046safe_meta(call(6,*,*,*,*,*,*)).
1047safe_meta('$tabling':start_tabling(*,0)).
1048safe_meta('$tabling':start_tabling(*,0,*,*)).
1049
1054
1055safe_output(Output) :-
1056 var(Output),
1057 !,
1058 instantiation_error(Output).
1059safe_output(atom(_)).
1060safe_output(string(_)).
1061safe_output(codes(_)).
1062safe_output(codes(_,_)).
1063safe_output(chars(_)).
1064safe_output(chars(_,_)).
1065safe_output(current_output).
1066safe_output(current_error).
1067
1071
1072:- public format_calls/3. 1073
1074format_calls(Format, _Args, _Calls) :-
1075 var(Format),
1076 !,
1077 instantiation_error(Format).
1078format_calls(Format, Args, Calls) :-
1079 format_types(Format, Types),
1080 ( format_callables(Types, Args, Calls)
1081 -> true
1082 ; throw(error(format_error(Format, Types, Args), _))
1083 ).
1084
1085format_callables([], [], []).
1086format_callables([callable|TT], [G|TA], [G|TG]) :-
1087 !,
1088 format_callables(TT, TA, TG).
1089format_callables([_|TT], [_|TA], TG) :-
1090 !,
1091 format_callables(TT, TA, TG).
1092
1093
1094 1097
1098:- multifile
1099 prolog:sandbox_allowed_directive/1,
1100 prolog:sandbox_allowed_goal/1,
1101 prolog:sandbox_allowed_expansion/1. 1102
1106
1107prolog:sandbox_allowed_directive(Directive) :-
1108 debug(sandbox(directive), 'Directive: ~p', [Directive]),
1109 fail.
1110prolog:sandbox_allowed_directive(Directive) :-
1111 safe_directive(Directive),
1112 !.
1113prolog:sandbox_allowed_directive(M:PredAttr) :-
1114 \+ prolog_load_context(module, M),
1115 !,
1116 debug(sandbox(directive), 'Cross-module directive', []),
1117 permission_error(execute, sandboxed_directive, (:- M:PredAttr)).
1118prolog:sandbox_allowed_directive(M:PredAttr) :-
1119 safe_pattr(PredAttr),
1120 !,
1121 PredAttr =.. [Attr, Preds],
1122 ( safe_pattr(Preds, Attr)
1123 -> true
1124 ; permission_error(execute, sandboxed_directive, (:- M:PredAttr))
1125 ).
1126prolog:sandbox_allowed_directive(_:Directive) :-
1127 safe_source_directive(Directive),
1128 !.
1129prolog:sandbox_allowed_directive(_:Directive) :-
1130 directive_loads_file(Directive, File),
1131 !,
1132 safe_path(File).
1133prolog:sandbox_allowed_directive(G) :-
1134 safe_goal(G).
1135
1150
1151
1152safe_pattr(dynamic(_)).
1153safe_pattr(thread_local(_)).
1154safe_pattr(volatile(_)).
1155safe_pattr(discontiguous(_)).
1156safe_pattr(multifile(_)).
1157safe_pattr(public(_)).
1158safe_pattr(meta_predicate(_)).
1159safe_pattr(table(_)).
1160safe_pattr(non_terminal(_)).
1161
1162safe_pattr(Var, _) :-
1163 var(Var),
1164 !,
1165 instantiation_error(Var).
1166safe_pattr((A,B), Attr) :-
1167 !,
1168 safe_pattr(A, Attr),
1169 safe_pattr(B, Attr).
1170safe_pattr(M:G, Attr) :-
1171 !,
1172 ( atom(M),
1173 prolog_load_context(module, M)
1174 -> true
1175 ; Goal =.. [Attr,M:G],
1176 permission_error(directive, sandboxed, (:- Goal))
1177 ).
1178safe_pattr(_, _).
1179
1180safe_source_directive(op(_,_,Name)) :-
1181 !,
1182 ( atom(Name)
1183 -> true
1184 ; is_list(Name),
1185 maplist(atom, Name)
1186 ).
1187safe_source_directive(set_prolog_flag(Flag, Value)) :-
1188 !,
1189 atom(Flag), ground(Value),
1190 safe_prolog_flag(Flag, Value).
1191safe_source_directive(style_check(_)).
1192safe_source_directive(initialization(_)). 1193safe_source_directive(initialization(_,_)). 1194
1195directive_loads_file(use_module(library(X)), X).
1196directive_loads_file(use_module(library(X), _Imports), X).
1197directive_loads_file(load_files(library(X), _Options), X).
1198directive_loads_file(ensure_loaded(library(X)), X).
1199directive_loads_file(include(X), X).
1200
1201safe_path(X) :-
1202 var(X),
1203 !,
1204 instantiation_error(X).
1205safe_path(X) :-
1206 ( atom(X)
1207 ; string(X)
1208 ),
1209 !,
1210 \+ sub_atom(X, 0, _, 0, '..'),
1211 \+ sub_atom(X, 0, _, _, '/'),
1212 \+ sub_atom(X, 0, _, _, '../'),
1213 \+ sub_atom(X, _, _, 0, '/..'),
1214 \+ sub_atom(X, _, _, _, '/../').
1215safe_path(A/B) :-
1216 !,
1217 safe_path(A),
1218 safe_path(B).
1219
1220
1229
1231safe_prolog_flag(generate_debug_info, _).
1232safe_prolog_flag(optimise, _).
1233safe_prolog_flag(occurs_check, _).
1235safe_prolog_flag(var_prefix, _).
1236safe_prolog_flag(double_quotes, _).
1237safe_prolog_flag(back_quotes, _).
1238safe_prolog_flag(rational_syntax, _).
1240safe_prolog_flag(prefer_rationals, _).
1241safe_prolog_flag(float_overflow, _).
1242safe_prolog_flag(float_zero_div, _).
1243safe_prolog_flag(float_undefined, _).
1244safe_prolog_flag(float_underflow, _).
1245safe_prolog_flag(float_rounding, _).
1246safe_prolog_flag(float_rounding, _).
1247safe_prolog_flag(max_rational_size, _).
1248safe_prolog_flag(max_rational_size_action, _).
1250safe_prolog_flag(max_answers_for_subgoal,_).
1251safe_prolog_flag(max_answers_for_subgoal_action,_).
1252safe_prolog_flag(max_table_answer_size,_).
1253safe_prolog_flag(max_table_answer_size_action,_).
1254safe_prolog_flag(max_table_subgoal_size,_).
1255safe_prolog_flag(max_table_subgoal_size_action,_).
1256
1257
1270
1271prolog:sandbox_allowed_expansion(M:G) :-
1272 prolog_load_context(module, M),
1273 !,
1274 debug(sandbox(expansion), 'Expand in ~p: ~p', [M, G]),
1275 safe_goal(M:G).
1276prolog:sandbox_allowed_expansion(_,_).
1277
1281
1282prolog:sandbox_allowed_goal(G) :-
1283 safe_goal(G).
1284
1285
1286 1289
1290:- multifile
1291 prolog:message//1,
1292 prolog:message_context//1,
1293 prolog:error_message//1. 1294
1295prolog:message(error(instantiation_error, Context)) -->
1296 { nonvar(Context),
1297 Context = sandbox(_Goal,Parents),
1298 numbervars(Context, 1, _)
1299 },
1300 [ 'Sandbox restriction!'-[], nl,
1301 'Could not derive which predicate may be called from'-[]
1302 ],
1303 ( { Parents == [] }
1304 -> [ 'Search space too large'-[] ]
1305 ; callers(Parents, 10)
1306 ).
1307
1308prolog:message_context(sandbox(_G, [])) --> !.
1309prolog:message_context(sandbox(_G, Parents)) -->
1310 [ nl, 'Reachable from:'-[] ],
1311 callers(Parents, 10).
1312
1313callers([], _) --> !.
1314callers(_, 0) --> !.
1315callers([G|Parents], Level) -->
1316 { NextLevel is Level-1
1317 },
1318 [ nl, '\t ~p'-[G] ],
1319 callers(Parents, NextLevel).
1320
1321prolog:message(bad_safe_declaration(Goal, File, Line)) -->
1322 [ '~w:~d: Invalid safe_primitive/1 declaration: ~p'-
1323 [File, Line, Goal] ].
1324
1325prolog:error_message(format_error(Format, Types, Args)) -->
1326 format_error(Format, Types, Args).
1327
1328format_error(Format, Types, Args) -->
1329 { length(Types, TypeLen),
1330 length(Args, ArgsLen),
1331 ( TypeLen > ArgsLen
1332 -> Problem = 'not enough'
1333 ; Problem = 'too many'
1334 )
1335 },
1336 [ 'format(~q): ~w arguments (found ~w, need ~w)'-
1337 [Format, Problem, ArgsLen, TypeLen]
1338 ]