34
35:- module(sandbox,
36 [ safe_goal/1, 37 safe_call/1 38 ]). 39:- use_module(library(assoc)). 40:- use_module(library(lists)). 41:- use_module(library(debug)). 42:- use_module(library(error)). 43:- use_module(library(prolog_format)). 44:- use_module(library(apply)). 45
46:- multifile
47 safe_primitive/1, 48 safe_meta_predicate/1, 49 safe_meta/2, 50 safe_meta/3, 51 safe_global_variable/1, 52 safe_directive/1. 53
55
68
69
70:- meta_predicate
71 safe_goal(:),
72 safe_call(0). 73
83
84safe_call(Goal0) :-
85 expand_goal(Goal0, Goal),
86 safe_goal(Goal),
87 call(Goal).
88
110
111safe_goal(M:Goal) :-
112 empty_assoc(Safe0),
113 catch(safe(Goal, M, [], Safe0, _), E, true),
114 !,
115 nb_delete(sandbox_last_error),
116 ( var(E)
117 -> true
118 ; throw(E)
119 ).
120safe_goal(_) :-
121 nb_current(sandbox_last_error, E),
122 !,
123 nb_delete(sandbox_last_error),
124 throw(E).
125safe_goal(G) :-
126 debug(sandbox(fail), 'safe_goal/1 failed for ~p', [G]),
127 throw(error(instantiation_error, sandbox(G, []))).
128
129
133
134safe(V, _, Parents, _, _) :-
135 var(V),
136 !,
137 Error = error(instantiation_error, sandbox(V, Parents)),
138 nb_setval(sandbox_last_error, Error),
139 throw(Error).
140safe(M:G, _, Parents, Safe0, Safe) :-
141 !,
142 must_be(atom, M),
143 must_be(callable, G),
144 ( predicate_property(M:G, imported_from(M2))
145 -> true
146 ; M2 = M
147 ),
148 ( ( safe_primitive(M2:G)
149 ; safe_primitive(G),
150 predicate_property(G, iso)
151 )
152 -> Safe = Safe0
153 ; ( predicate_property(M:G, exported)
154 ; predicate_property(M:G, public)
155 ; predicate_property(M:G, multifile)
156 ; predicate_property(M:G, iso)
157 ; memberchk(M:_, Parents)
158 )
159 -> safe(G, M, Parents, Safe0, Safe)
160 ; throw(error(permission_error(call, sandboxed, M:G),
161 sandbox(M:G, Parents)))
162 ).
163safe(G, _, Parents, _, _) :-
164 debugging(sandbox(show)),
165 length(Parents, Level),
166 debug(sandbox(show), '[~D] SAFE ~q?', [Level, G]),
167 fail.
168safe(G, _, Parents, Safe, Safe) :-
169 catch(safe_primitive(G),
170 error(instantiation_error, _),
171 rethrow_instantition_error([G|Parents])),
172 predicate_property(G, iso),
173 !.
174safe(G, M, Parents, Safe, Safe) :-
175 ( predicate_property(M:G, imported_from(M2))
176 -> true
177 ; M2 = M
178 ),
179 ( catch(safe_primitive(M2:G),
180 error(instantiation_error, _),
181 rethrow_instantition_error([M2:G|Parents]))
182 ; predicate_property(M2:G, number_of_rules(0))
183 ),
184 !.
185safe(G, M, Parents, Safe0, Safe) :-
186 predicate_property(G, iso),
187 safe_meta_call(G, M, Called),
188 !,
189 safe_list(Called, M, Parents, Safe0, Safe).
190safe(G, M, Parents, Safe0, Safe) :-
191 ( predicate_property(M:G, imported_from(M2))
192 -> true
193 ; M2 = M
194 ),
195 safe_meta_call(M2:G, M, Called),
196 !,
197 safe_list(Called, M, Parents, Safe0, Safe).
198safe(G, M, Parents, Safe0, Safe) :-
199 goal_id(M:G, Id, Gen),
200 ( get_assoc(Id, Safe0, _)
201 -> Safe = Safe0
202 ; put_assoc(Id, Safe0, true, Safe1),
203 ( Gen == M:G
204 -> safe_clauses(Gen, M, [Id|Parents], Safe1, Safe)
205 ; catch(safe_clauses(Gen, M, [Id|Parents], Safe1, Safe),
206 error(instantiation_error, Ctx),
207 unsafe(Parents, Ctx))
208 )
209 ),
210 !.
211safe(G, M, Parents, _, _) :-
212 debug(sandbox(fail),
213 'safe/1 failed for ~p (parents:~p)', [M:G, Parents]),
214 fail.
215
216unsafe(Parents, Var) :-
217 var(Var),
218 !,
219 nb_setval(sandbox_last_error,
220 error(instantiation_error, sandbox(_, Parents))),
221 fail.
222unsafe(_Parents, Ctx) :-
223 Ctx = sandbox(_,_),
224 nb_setval(sandbox_last_error,
225 error(instantiation_error, Ctx)),
226 fail.
227
228rethrow_instantition_error(Parents) :-
229 throw(error(instantiation_error, sandbox(_, Parents))).
230
231safe_clauses(G, M, Parents, Safe0, Safe) :-
232 predicate_property(M:G, interpreted),
233 def_module(M:G, MD:QG),
234 \+ compiled(MD:QG),
235 !,
236 findall(Ref-Body, clause(MD:QG, Body, Ref), Bodies),
237 safe_bodies(Bodies, MD, Parents, Safe0, Safe).
238safe_clauses(G, M, [_|Parents], _, _) :-
239 predicate_property(M:G, visible),
240 !,
241 throw(error(permission_error(call, sandboxed, G),
242 sandbox(M:G, Parents))).
243safe_clauses(_, _, [G|Parents], _, _) :-
244 throw(error(existence_error(procedure, G),
245 sandbox(G, Parents))).
246
247compiled(system:(@(_,_))).
248
254
255safe_bodies([], _, _, Safe, Safe).
256safe_bodies([Ref-H|T], M, Parents, Safe0, Safe) :-
257 ( H = M2:H2, nonvar(M2),
258 clause_property(Ref, module(M2))
259 -> copy_term(H2, H3),
260 CM = M2
261 ; copy_term(H, H3),
262 CM = M
263 ),
264 safe(H3, CM, Parents, Safe0, Safe1),
265 safe_bodies(T, M, Parents, Safe1, Safe).
266
267def_module(M:G, MD:QG) :-
268 predicate_property(M:G, imported_from(MD)),
269 !,
270 meta_qualify(MD:G, M, QG).
271def_module(M:G, M:QG) :-
272 meta_qualify(M:G, M, QG).
273
279
280safe_list([], _, _, Safe, Safe).
281safe_list([H|T], M, Parents, Safe0, Safe) :-
282 ( H = M2:H2,
283 M == M2 284 -> copy_term(H2, H3)
285 ; copy_term(H, H3) 286 ),
287 safe(H3, M, Parents, Safe0, Safe1),
288 safe_list(T, M, Parents, Safe1, Safe).
289
293
294meta_qualify(MD:G, M, QG) :-
295 predicate_property(MD:G, meta_predicate(Head)),
296 !,
297 G =.. [Name|Args],
298 Head =.. [_|Q],
299 qualify_args(Q, M, Args, QArgs),
300 QG =.. [Name|QArgs].
301meta_qualify(_:G, _, G).
302
303qualify_args([], _, [], []).
304qualify_args([H|T], M, [A|AT], [Q|QT]) :-
305 qualify_arg(H, M, A, Q),
306 qualify_args(T, M, AT, QT).
307
308qualify_arg(S, M, A, Q) :-
309 q_arg(S),
310 !,
311 qualify(A, M, Q).
312qualify_arg(_, _, A, A).
313
314q_arg(I) :- integer(I), !.
315q_arg(:).
316q_arg(^).
317q_arg(//).
318
319qualify(A, M, MZ:Q) :-
320 strip_module(M:A, MZ, Q).
321
331
332goal_id(M:Goal, M:Id, Gen) :-
333 !,
334 goal_id(Goal, Id, Gen).
335goal_id(Var, _, _) :-
336 var(Var),
337 !,
338 instantiation_error(Var).
339goal_id(Atom, Atom, Atom) :-
340 atom(Atom),
341 !.
342goal_id(Term, _, _) :-
343 \+ compound(Term),
344 !,
345 type_error(callable, Term).
346goal_id(Term, Skolem, Gen) :- 347 compound_name_arity(Term, Name, Arity),
348 compound_name_arity(Skolem, Name, Arity),
349 compound_name_arity(Gen, Name, Arity),
350 copy_goal_args(1, Term, Skolem, Gen),
351 ( Gen =@= Term
352 -> ! 353 ; true
354 ),
355 numbervars(Skolem, 0, _).
356goal_id(Term, Skolem, Term) :- 357 debug(sandbox(specify), 'Retrying with ~p', [Term]),
358 copy_term(Term, Skolem),
359 numbervars(Skolem, 0, _).
360
365
366copy_goal_args(I, Term, Skolem, Gen) :-
367 arg(I, Term, TA),
368 !,
369 arg(I, Skolem, SA),
370 arg(I, Gen, GA),
371 copy_goal_arg(TA, SA, GA),
372 I2 is I + 1,
373 copy_goal_args(I2, Term, Skolem, Gen).
374copy_goal_args(_, _, _, _).
375
376copy_goal_arg(Arg, SArg, Arg) :-
377 copy_goal_arg(Arg),
378 !,
379 copy_term(Arg, SArg).
380copy_goal_arg(_, _, _).
381
382copy_goal_arg(Var) :- var(Var), !, fail.
383copy_goal_arg(_:_).
384
394
395term_expansion(safe_primitive(Goal), Term) :-
396 ( verify_safe_declaration(Goal)
397 -> Term = safe_primitive(Goal)
398 ; Term = []
399 ).
400
401system:term_expansion(sandbox:safe_primitive(Goal), Term) :-
402 \+ current_prolog_flag(xref, true),
403 ( verify_safe_declaration(Goal)
404 -> Term = sandbox:safe_primitive(Goal)
405 ; Term = []
406 ).
407
408verify_safe_declaration(Var) :-
409 var(Var),
410 !,
411 instantiation_error(Var).
412verify_safe_declaration(Module:Goal) :-
413 must_be(atom, Module),
414 must_be(callable, Goal),
415 ( ok_meta(Module:Goal)
416 -> true
417 ; ( predicate_property(Module:Goal, visible)
418 -> true
419 ; predicate_property(Module:Goal, foreign)
420 ),
421 \+ predicate_property(Module:Goal, imported_from(_)),
422 \+ predicate_property(Module:Goal, meta_predicate(_))
423 -> true
424 ; permission_error(declare, safe_goal, Module:Goal)
425 ).
426verify_safe_declaration(Goal) :-
427 must_be(callable, Goal),
428 ( predicate_property(system:Goal, iso),
429 \+ predicate_property(system:Goal, meta_predicate())
430 -> true
431 ; permission_error(declare, safe_goal, Goal)
432 ).
433
434ok_meta(system:assert(_)).
435ok_meta(system:use_module(_,_)).
436ok_meta(system:use_module(_)).
437
438verify_predefined_safe_declarations :-
439 forall(clause(safe_primitive(Goal), _Body, Ref),
440 ( catch(verify_safe_declaration(Goal), E, true),
441 ( nonvar(E)
442 -> clause_property(Ref, file(File)),
443 clause_property(Ref, line_count(Line)),
444 print_message(error, bad_safe_declaration(Goal, File, Line))
445 ; true
446 )
447 )).
448
449:- initialization(verify_predefined_safe_declarations, now). 450
462
464
465safe_primitive(true).
466safe_primitive(fail).
467safe_primitive(system:false).
468safe_primitive(repeat).
469safe_primitive(!).
470 471safe_primitive(var(_)).
472safe_primitive(nonvar(_)).
473safe_primitive(system:attvar(_)).
474safe_primitive(integer(_)).
475safe_primitive(float(_)).
476safe_primitive(system:rational(_)).
477safe_primitive(number(_)).
478safe_primitive(atom(_)).
479safe_primitive(system:blob(_,_)).
480safe_primitive(system:string(_)).
481safe_primitive(atomic(_)).
482safe_primitive(compound(_)).
483safe_primitive(callable(_)).
484safe_primitive(ground(_)).
485safe_primitive(system:cyclic_term(_)).
486safe_primitive(acyclic_term(_)).
487safe_primitive(system:is_stream(_)).
488safe_primitive(system:'$is_char'(_)).
489safe_primitive(system:'$is_char_code'(_)).
490safe_primitive(system:'$is_char_list'(_,_)).
491safe_primitive(system:'$is_code_list'(_,_)).
492 493safe_primitive(@>(_,_)).
494safe_primitive(@>=(_,_)).
495safe_primitive(==(_,_)).
496safe_primitive(@<(_,_)).
497safe_primitive(@=<(_,_)).
498safe_primitive(compare(_,_,_)).
499safe_primitive(sort(_,_)).
500safe_primitive(keysort(_,_)).
501safe_primitive(system: =@=(_,_)).
502safe_primitive(system:'$btree_find_node'(_,_,_,_)).
503
504 505safe_primitive(=(_,_)).
506safe_primitive(\=(_,_)).
507safe_primitive(system:'?='(_,_)).
508safe_primitive(system:unifiable(_,_,_)).
509safe_primitive(unify_with_occurs_check(_,_)).
510safe_primitive(\==(_,_)).
511 512safe_primitive(is(_,_)).
513safe_primitive(>(_,_)).
514safe_primitive(>=(_,_)).
515safe_primitive(=:=(_,_)).
516safe_primitive(=\=(_,_)).
517safe_primitive(=<(_,_)).
518safe_primitive(<(_,_)).
519 520safe_primitive(arg(_,_,_)).
521safe_primitive(system:setarg(_,_,_)).
522safe_primitive(system:nb_setarg(_,_,_)).
523safe_primitive(system:nb_linkarg(_,_,_)).
524safe_primitive(functor(_,_,_)).
525safe_primitive(_ =.. _).
526safe_primitive(system:compound_name_arity(_,_,_)).
527safe_primitive(system:compound_name_arguments(_,_,_)).
528safe_primitive(system:'$filled_array'(_,_,_,_)).
529safe_primitive(copy_term(_,_)).
530safe_primitive(system:duplicate_term(_,_)).
531safe_primitive(system:copy_term_nat(_,_)).
532safe_primitive(numbervars(_,_,_)).
533safe_primitive(subsumes_term(_,_)).
534safe_primitive(system:term_hash(_,_)).
535safe_primitive(system:term_hash(_,_,_,_)).
536safe_primitive(system:variant_sha1(_,_)).
537safe_primitive(system:variant_hash(_,_)).
538safe_primitive(system:'$term_size'(_,_,_)).
539
540 541safe_primitive(system:is_dict(_)).
542safe_primitive(system:is_dict(_,_)).
543safe_primitive(system:get_dict(_,_,_)).
544safe_primitive(system:get_dict(_,_,_,_,_)).
545safe_primitive(system:'$get_dict_ex'(_,_,_)).
546safe_primitive(system:dict_create(_,_,_)).
547safe_primitive(system:dict_pairs(_,_,_)).
548safe_primitive(system:put_dict(_,_,_)).
549safe_primitive(system:put_dict(_,_,_,_)).
550safe_primitive(system:del_dict(_,_,_,_)).
551safe_primitive(system:select_dict(_,_,_)).
552safe_primitive(system:b_set_dict(_,_,_)).
553safe_primitive(system:nb_set_dict(_,_,_)).
554safe_primitive(system:nb_link_dict(_,_,_)).
555safe_primitive(system:(:<(_,_))).
556safe_primitive(system:(>:<(_,_))).
557 558safe_primitive(atom_chars(_, _)).
559safe_primitive(atom_codes(_, _)).
560safe_primitive(sub_atom(_,_,_,_,_)).
561safe_primitive(atom_concat(_,_,_)).
562safe_primitive(atom_length(_,_)).
563safe_primitive(char_code(_,_)).
564safe_primitive(system:name(_,_)).
565safe_primitive(system:atomic_concat(_,_,_)).
566safe_primitive(system:atomic_list_concat(_,_)).
567safe_primitive(system:atomic_list_concat(_,_,_)).
568safe_primitive(system:downcase_atom(_,_)).
569safe_primitive(system:upcase_atom(_,_)).
570safe_primitive(system:char_type(_,_)).
571safe_primitive(system:normalize_space(_,_)).
572safe_primitive(system:sub_atom_icasechk(_,_,_)).
573 574safe_primitive(number_codes(_,_)).
575safe_primitive(number_chars(_,_)).
576safe_primitive(system:atom_number(_,_)).
577safe_primitive(system:code_type(_,_)).
578 579safe_primitive(system:atom_string(_,_)).
580safe_primitive(system:number_string(_,_)).
581safe_primitive(system:string_chars(_, _)).
582safe_primitive(system:string_codes(_, _)).
583safe_primitive(system:string_code(_,_,_)).
584safe_primitive(system:sub_string(_,_,_,_,_)).
585safe_primitive(system:split_string(_,_,_,_)).
586safe_primitive(system:atomics_to_string(_,_,_)).
587safe_primitive(system:atomics_to_string(_,_)).
588safe_primitive(system:string_concat(_,_,_)).
589safe_primitive(system:string_length(_,_)).
590safe_primitive(system:string_lower(_,_)).
591safe_primitive(system:string_upper(_,_)).
592safe_primitive(system:term_string(_,_)).
593safe_primitive('$syspreds':term_string(_,_,_)).
594 595safe_primitive(length(_,_)).
596 597safe_primitive(throw(_)).
598safe_primitive(system:abort).
599 600safe_primitive(current_prolog_flag(_,_)).
601safe_primitive(current_op(_,_,_)).
602safe_primitive(system:sleep(_)).
603safe_primitive(system:thread_self(_)).
604safe_primitive(system:get_time(_)).
605safe_primitive(system:statistics(_,_)).
606safe_primitive(system:thread_statistics(Id,_,_)) :-
607 ( var(Id)
608 -> instantiation_error(Id)
609 ; thread_self(Id)
610 ).
611safe_primitive(system:thread_property(Id,_)) :-
612 ( var(Id)
613 -> instantiation_error(Id)
614 ; thread_self(Id)
615 ).
616safe_primitive(system:format_time(_,_,_)).
617safe_primitive(system:format_time(_,_,_,_)).
618safe_primitive(system:date_time_stamp(_,_)).
619safe_primitive(system:stamp_date_time(_,_,_)).
620safe_primitive(system:strip_module(_,_,_)).
621safe_primitive('$messages':message_to_string(_,_)).
622safe_primitive(system:import_module(_,_)).
623safe_primitive(system:file_base_name(_,_)).
624safe_primitive(system:file_directory_name(_,_)).
625safe_primitive(system:file_name_extension(_,_,_)).
626
627safe_primitive(clause(H,_)) :- safe_clause(H).
628safe_primitive(asserta(X)) :- safe_assert(X).
629safe_primitive(assertz(X)) :- safe_assert(X).
630safe_primitive(retract(X)) :- safe_assert(X).
631safe_primitive(retractall(X)) :- safe_assert(X).
632
636safe_primitive('$dicts':'.'(_,K,_)) :- atom(K).
637safe_primitive('$dicts':'.'(_,K,_)) :-
638 ( nonvar(K)
639 -> dict_built_in(K)
640 ; instantiation_error(K)
641 ).
642
643dict_built_in(get(_)).
644dict_built_in(put(_)).
645dict_built_in(put(_,_)).
646
649
650safe_primitive(system:false).
651safe_primitive(system:cyclic_term(_)).
652safe_primitive(system:msort(_,_)).
653safe_primitive(system:sort(_,_,_,_)).
654safe_primitive(system:between(_,_,_)).
655safe_primitive(system:succ(_,_)).
656safe_primitive(system:plus(_,_,_)).
657safe_primitive(system:term_variables(_,_)).
658safe_primitive(system:term_variables(_,_,_)).
659safe_primitive(system:'$term_size'(_,_,_)).
660safe_primitive(system:atom_to_term(_,_,_)).
661safe_primitive(system:term_to_atom(_,_)).
662safe_primitive(system:atomic_list_concat(_,_,_)).
663safe_primitive(system:atomic_list_concat(_,_)).
664safe_primitive(system:downcase_atom(_,_)).
665safe_primitive(system:upcase_atom(_,_)).
666safe_primitive(system:is_list(_)).
667safe_primitive(system:memberchk(_,_)).
668safe_primitive(system:'$skip_list'(_,_,_)).
669 670safe_primitive(system:get_attr(_,_,_)).
671safe_primitive(system:get_attrs(_,_)).
672safe_primitive(system:term_attvars(_,_)).
673safe_primitive(system:del_attr(_,_)).
674safe_primitive(system:del_attrs(_)).
675safe_primitive('$attvar':copy_term(_,_,_)).
676 677safe_primitive(system:b_getval(_,_)).
678safe_primitive(system:b_setval(Var,_)) :-
679 safe_global_var(Var).
680safe_primitive(system:nb_getval(_,_)).
681safe_primitive('$syspreds':nb_setval(Var,_)) :-
682 safe_global_var(Var).
683safe_primitive(system:nb_current(_,_)).
684 685safe_primitive(system:assert(X)) :-
686 safe_assert(X).
687 688safe_primitive(system:writeln(_)).
689safe_primitive('$messages':print_message(_,_)).
690
691 692safe_primitive('$syspreds':set_prolog_stack(Stack, limit(ByteExpr))) :-
693 nonvar(Stack),
694 stack_name(Stack),
695 catch(Bytes is ByteExpr, _, fail),
696 prolog_stack_property(Stack, limit(Current)),
697 Bytes =< Current.
698
699stack_name(global).
700stack_name(local).
701stack_name(trail).
702
703
706
707safe_primitive(system:use_module(Spec, _Import)) :-
708 safe_primitive(system:use_module(Spec)).
709safe_primitive(system:use_module(Spec)) :-
710 ground(Spec),
711 ( atom(Spec)
712 -> Path = Spec
713 ; Spec =.. [_Alias, Segments],
714 phrase(segments_to_path(Segments), List),
715 atomic_list_concat(List, Path)
716 ),
717 \+ is_absolute_file_name(Path),
718 \+ sub_atom(Path, _, _, _, '/../'),
719 absolute_file_name(Spec, AbsFile,
720 [ access(read),
721 file_type(prolog),
722 file_errors(fail)
723 ]),
724 file_name_extension(_, Ext, AbsFile),
725 save_extension(Ext).
726
729
730segments_to_path(A/B) -->
731 !,
732 segments_to_path(A),
733 [/],
734 segments_to_path(B).
735segments_to_path(X) -->
736 [X].
737
738save_extension(pl).
739
746
747safe_assert(C) :- cyclic_term(C), !, fail.
748safe_assert(X) :- var(X), !, fail.
749safe_assert(_Head:-_Body) :- !, fail.
750safe_assert(_:_) :- !, fail.
751safe_assert(_).
752
758
759safe_clause(H) :- var(H), !.
760safe_clause(_:_) :- !, fail.
761safe_clause(_).
762
763
768
769safe_global_var(Name) :-
770 var(Name),
771 !,
772 instantiation_error(Name).
773safe_global_var(Name) :-
774 safe_global_variable(Name).
775
779
780
785
786safe_meta(system:put_attr(V,M,A), Called) :-
787 !,
788 ( atom(M)
789 -> attr_hook_predicates([ attr_unify_hook(A, _),
790 attribute_goals(V,_,_),
791 project_attributes(_,_)
792 ], M, Called)
793 ; instantiation_error(M)
794 ).
795safe_meta(system:with_output_to(Output, G), [G]) :-
796 safe_output(Output),
797 !.
798safe_meta(system:format(Format, Args), Calls) :-
799 format_calls(Format, Args, Calls).
800safe_meta(system:format(Output, Format, Args), Calls) :-
801 safe_output(Output),
802 format_calls(Format, Args, Calls).
803safe_meta(prolog_debug:debug(_Term, Format, Args), Calls) :-
804 format_calls(Format, Args, Calls).
805safe_meta('$attvar':freeze(_Var,Goal), [Goal]).
806safe_meta(phrase(NT,Xs0,Xs), [Goal]) :- 807 expand_nt(NT,Xs0,Xs,Goal).
808safe_meta(phrase(NT,Xs0), [Goal]) :-
809 expand_nt(NT,Xs0,[],Goal).
810safe_meta('$dcg':call_dcg(NT,Xs0,Xs), [Goal]) :-
811 expand_nt(NT,Xs0,Xs,Goal).
812safe_meta('$dcg':call_dcg(NT,Xs0), [Goal]) :-
813 expand_nt(NT,Xs0,[],Goal).
814
822
823attr_hook_predicates([], _, []).
824attr_hook_predicates([H|T], M, Called) :-
825 ( predicate_property(M:H, defined)
826 -> Called = [M:H|Rest]
827 ; Called = Rest
828 ),
829 attr_hook_predicates(T, M, Rest).
830
831
836
837expand_nt(NT, _Xs0, _Xs, _NewGoal) :-
838 strip_module(NT, _, Plain),
839 var(Plain),
840 !,
841 instantiation_error(Plain).
842expand_nt(NT, Xs0, Xs, NewGoal) :-
843 dcg_translate_rule((pseudo_nt --> NT),
844 (pseudo_nt(Xs0c,Xsc) :- NewGoal0)),
845 ( var(Xsc), Xsc \== Xs0c
846 -> Xs = Xsc, NewGoal1 = NewGoal0
847 ; NewGoal1 = (NewGoal0, Xsc = Xs)
848 ),
849 ( var(Xs0c)
850 -> Xs0 = Xs0c,
851 NewGoal = NewGoal1
852 ; NewGoal = ( Xs0 = Xs0c, NewGoal1 )
853 ).
854
859
860safe_meta_call(Goal, _, _Called) :-
861 debug(sandbox(meta), 'Safe meta ~p?', [Goal]),
862 fail.
863safe_meta_call(Goal, Context, Called) :-
864 ( safe_meta(Goal, Called)
865 -> true
866 ; safe_meta(Goal, Context, Called)
867 ),
868 !. 869safe_meta_call(Goal, _, Called) :-
870 Goal = M:Plain,
871 compound(Plain),
872 compound_name_arity(Plain, Name, Arity),
873 safe_meta_predicate(M:Name/Arity),
874 predicate_property(Goal, meta_predicate(Spec)),
875 !,
876 findall(C, called(Spec, Plain, C), Called).
877safe_meta_call(M:Goal, _, Called) :-
878 !,
879 generic_goal(Goal, Gen),
880 safe_meta(M:Gen),
881 findall(C, called(Gen, Goal, C), Called).
882safe_meta_call(Goal, _, Called) :-
883 generic_goal(Goal, Gen),
884 safe_meta(Gen),
885 findall(C, called(Gen, Goal, C), Called).
886
887called(Gen, Goal, Called) :-
888 arg(I, Gen, Spec),
889 calling_meta_spec(Spec),
890 arg(I, Goal, Called0),
891 extend(Spec, Called0, Called).
892
893generic_goal(G, Gen) :-
894 functor(G, Name, Arity),
895 functor(Gen, Name, Arity).
896
897calling_meta_spec(V) :- var(V), !, fail.
898calling_meta_spec(I) :- integer(I), !.
899calling_meta_spec(^).
900calling_meta_spec(//).
901
902
903extend(^, G, Plain) :-
904 !,
905 strip_existential(G, Plain).
906extend(//, DCG, Goal) :-
907 !,
908 ( expand_phrase(call_dcg(DCG,_,_), Goal)
909 -> true
910 ; instantiation_error(DCG) 911 ). 912extend(0, G, G) :- !.
913extend(I, M:G0, M:G) :-
914 !,
915 G0 =.. List,
916 length(Extra, I),
917 append(List, Extra, All),
918 G =.. All.
919extend(I, G0, G) :-
920 G0 =.. List,
921 length(Extra, I),
922 append(List, Extra, All),
923 G =.. All.
924
925strip_existential(Var, Var) :-
926 var(Var),
927 !.
928strip_existential(M:G0, M:G) :-
929 !,
930 strip_existential(G0, G).
931strip_existential(_^G0, G) :-
932 !,
933 strip_existential(G0, G).
934strip_existential(G, G).
935
937
938safe_meta((0,0)).
939safe_meta((0;0)).
940safe_meta((0->0)).
941safe_meta(system:(0*->0)).
942safe_meta(catch(0,*,0)).
943safe_meta(findall(*,0,*)).
944safe_meta('$bags':findall(*,0,*,*)).
945safe_meta(setof(*,^,*)).
946safe_meta(bagof(*,^,*)).
947safe_meta('$bags':findnsols(*,*,0,*)).
948safe_meta('$bags':findnsols(*,*,0,*,*)).
949safe_meta(system:call_cleanup(0,0)).
950safe_meta(system:setup_call_cleanup(0,0,0)).
951safe_meta(system:setup_call_catcher_cleanup(0,0,*,0)).
952safe_meta('$attvar':call_residue_vars(0,*)).
953safe_meta('$syspreds':call_with_inference_limit(0,*,*)).
954safe_meta('$syspreds':call_with_depth_limit(0,*,*)).
955safe_meta(^(*,0)).
956safe_meta(\+(0)).
957safe_meta(call(0)).
958safe_meta(call(1,*)).
959safe_meta(call(2,*,*)).
960safe_meta(call(3,*,*,*)).
961safe_meta(call(4,*,*,*,*)).
962safe_meta(call(5,*,*,*,*,*)).
963safe_meta(call(6,*,*,*,*,*,*)).
964
965
970
971safe_output(Output) :-
972 var(Output),
973 !,
974 instantiation_error(Output).
975safe_output(atom(_)).
976safe_output(string(_)).
977safe_output(codes(_)).
978safe_output(codes(_,_)).
979safe_output(chars(_)).
980safe_output(chars(_,_)).
981safe_output(current_output).
982safe_output(current_error).
983
987
988:- public format_calls/3. 989
990format_calls(Format, _Args, _Calls) :-
991 var(Format),
992 !,
993 instantiation_error(Format).
994format_calls(Format, Args, Calls) :-
995 format_types(Format, Types),
996 ( format_callables(Types, Args, Calls)
997 -> true
998 ; throw(error(format_error(Format, Types, Args), _))
999 ).
1000
1001format_callables([], [], []).
1002format_callables([callable|TT], [G|TA], [G|TG]) :-
1003 !,
1004 format_callables(TT, TA, TG).
1005format_callables([_|TT], [_|TA], TG) :-
1006 !,
1007 format_callables(TT, TA, TG).
1008
1009
1010 1013
1014:- multifile
1015 prolog:sandbox_allowed_directive/1,
1016 prolog:sandbox_allowed_goal/1,
1017 prolog:sandbox_allowed_expansion/1. 1018
1022
1023prolog:sandbox_allowed_directive(Directive) :-
1024 debug(sandbox(directive), 'Directive: ~p', [Directive]),
1025 fail.
1026prolog:sandbox_allowed_directive(Directive) :-
1027 safe_directive(Directive),
1028 !.
1029prolog:sandbox_allowed_directive(M:PredAttr) :-
1030 \+ prolog_load_context(module, M),
1031 !,
1032 debug(sandbox(directive), 'Cross-module directive', []),
1033 permission_error(execute, sandboxed_directive, (:- M:PredAttr)).
1034prolog:sandbox_allowed_directive(M:PredAttr) :-
1035 safe_pattr(PredAttr),
1036 !,
1037 PredAttr =.. [Attr, Preds],
1038 ( safe_pattr(Preds, Attr)
1039 -> true
1040 ; permission_error(execute, sandboxed_directive, (:- M:PredAttr))
1041 ).
1042prolog:sandbox_allowed_directive(_:Directive) :-
1043 safe_source_directive(Directive),
1044 !.
1045prolog:sandbox_allowed_directive(_:Directive) :-
1046 directive_loads_file(Directive, File),
1047 !,
1048 safe_path(File).
1049prolog:sandbox_allowed_directive(G) :-
1050 safe_goal(G).
1051
1066
1067
1068safe_pattr(dynamic(_)).
1069safe_pattr(thread_local(_)).
1070safe_pattr(volatile(_)).
1071safe_pattr(discontiguous(_)).
1072safe_pattr(multifile(_)).
1073safe_pattr(public(_)).
1074safe_pattr(meta_predicate(_)).
1075
1076safe_pattr(Var, _) :-
1077 var(Var),
1078 !,
1079 instantiation_error(Var).
1080safe_pattr((A,B), Attr) :-
1081 !,
1082 safe_pattr(A, Attr),
1083 safe_pattr(B, Attr).
1084safe_pattr(M:G, Attr) :-
1085 !,
1086 ( atom(M),
1087 prolog_load_context(module, M)
1088 -> true
1089 ; Goal =.. [Attr,M:G],
1090 permission_error(directive, sandboxed, (:- Goal))
1091 ).
1092safe_pattr(_, _).
1093
1094safe_source_directive(op(_,_,Name)) :-
1095 !,
1096 ( atom(Name)
1097 -> true
1098 ; is_list(Name),
1099 maplist(atom, Name)
1100 ).
1101safe_source_directive(set_prolog_flag(Flag, Value)) :-
1102 !,
1103 atom(Flag), ground(Value),
1104 safe_directive_flag(Flag, Value).
1105safe_source_directive(style_check(_)).
1106safe_source_directive(initialization(_)). 1107safe_source_directive(initialization(_,_)). 1108
1109directive_loads_file(use_module(library(X)), X).
1110directive_loads_file(use_module(library(X), _Imports), X).
1111directive_loads_file(ensure_loaded(library(X)), X).
1112directive_loads_file(include(X), X).
1113
1114safe_path(X) :-
1115 var(X),
1116 !,
1117 instantiation_error(X).
1118safe_path(X) :-
1119 ( atom(X)
1120 ; string(X)
1121 ),
1122 !,
1123 \+ sub_atom(X, 0, _, 0, '..'),
1124 \+ sub_atom(X, 0, _, _, '/'),
1125 \+ sub_atom(X, 0, _, _, '../'),
1126 \+ sub_atom(X, _, _, 0, '/..'),
1127 \+ sub_atom(X, _, _, _, '/../').
1128safe_path(A/B) :-
1129 !,
1130 safe_path(A),
1131 safe_path(B).
1132
1133
1142
1143safe_directive_flag(generate_debug_info, _).
1144safe_directive_flag(var_prefix, _).
1145safe_directive_flag(double_quotes, _).
1146safe_directive_flag(back_quotes, _).
1147
1160
1161prolog:sandbox_allowed_expansion(Directive) :-
1162 prolog_load_context(module, M),
1163 debug(sandbox(expansion), 'Expand in ~p: ~p', [M, Directive]),
1164 fail.
1165prolog:sandbox_allowed_expansion(M:G) :-
1166 prolog_load_context(module, M),
1167 !,
1168 safe_goal(M:G).
1169prolog:sandbox_allowed_expansion(_,_).
1170
1174
1175prolog:sandbox_allowed_goal(G) :-
1176 safe_goal(G).
1177
1178
1179 1182
1183:- multifile
1184 prolog:message//1,
1185 prolog:message_context//1,
1186 prolog:error_message//1. 1187
1188prolog:message_context(sandbox(_G, [])) --> !.
1189prolog:message_context(sandbox(_G, Parents)) -->
1190 [ nl, 'Reachable from:'-[] ],
1191 callers(Parents, 10).
1192
1193callers([], _) --> !.
1194callers(_, 0) --> !.
1195callers([G|Parents], Level) -->
1196 { NextLevel is Level-1
1197 },
1198 [ nl, '\t ~p'-[G] ],
1199 callers(Parents, NextLevel).
1200
1201prolog:message(bad_safe_declaration(Goal, File, Line)) -->
1202 [ '~w:~d: Invalid safe_primitive/1 declaration: ~p'-
1203 [File, Line, Goal] ].
1204
1205prolog:error_message(format_error(Format, Types, Args)) -->
1206 format_error(Format, Types, Args).
1207
1208format_error(Format, Types, Args) -->
1209 { length(Types, TypeLen),
1210 length(Args, ArgsLen),
1211 ( TypeLen > ArgsLen
1212 -> Problem = 'not enough'
1213 ; Problem = 'too many'
1214 )
1215 },
1216 [ 'format(~q): ~w arguments (found ~w, need ~w)'-
1217 [Format, Problem, ArgsLen, TypeLen]
1218 ]