From: Han-Wen Nienhuys Date: Sun, 9 May 2004 11:15:48 +0000 (+0000) Subject: * scm/output-tex.scm (output-tex-string): tighten safe security. X-Git-Tag: release/2.3.1~2 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=d3b59ed445baf28ffd933df4620d5bc143f862ec;p=lilypond.git * scm/output-tex.scm (output-tex-string): tighten safe security. * lily/scm-option.cc (LY_DEFINE): add 'safe to ly:get-option * scm/safe-lily.scm (make-safe-lilypond-module): new file. Define allowed ly functions. --- diff --git a/ChangeLog b/ChangeLog index 3628f227e0..4667ce6314 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,8 +9,16 @@ 2004-05-09 Han-Wen Nienhuys + * scm/output-tex.scm (output-tex-string): tighten safe security. + + * lily/scm-option.cc (LY_DEFINE): add 'safe to ly:get-option + + * scm/safe-lily.scm (make-safe-lilypond-module): new file. Define + allowed ly functions. + * lily/ly-module.cc (ly_module_define): only define variable if bound. + (ly_make_anonymous_module): take safe option. 2004-05-08 Han-Wen Nienhuys diff --git a/Documentation/topdocs/NEWS.texi b/Documentation/topdocs/NEWS.texi index ed74083923..1476b409ea 100644 --- a/Documentation/topdocs/NEWS.texi +++ b/Documentation/topdocs/NEWS.texi @@ -7,18 +7,21 @@ @unnumbered New features in 2.3 since 2.2 @itemize @bullet - +@item The @code{--safe} mode has been revisited: it makes the basic +ly: interface available, and makes prevents Scheme or @TeX{} code. @item Music syntax can now be extended seamlessly. As an example, -here is the new implementation @code{\apply}, +here is the new implementation @code{\applymusic}, @example - apply = #(ly:make-music-function + applymusic = #(ly:make-music-function (list procedure? ly:music?) ; signature (lambda (where func music) ; the function (func music))) @end example +@item @code{\apply} has been renamed to @code{\applymusic}. + @item Music can be used as a markup. When inserting a @code{score} block as part of a @code{\markup}, it produces a rendered markup of the music. @@ -29,10 +32,9 @@ it produces a rendered markup of the music. @item LilyPond expressions can be embedded into Scheme. The syntax for -this is @code{#@{ ... #@}}. Within such a block, Scheme forms, for -instance variable names, can be introduced thanks to a @code{$} -character (@code{$$} results in a single `$' character). These forms -are then printed in the pattern. +this is @code{#@{ ... #@}}. Within such a block, Scheme forms can be +introduced using a @code{$} character (@code{$$} results in a single +`$' character). These forms are then printed in the pattern. @example #(define (textoffset dx dy) @@ -50,16 +52,7 @@ are then printed in the pattern. @} @end example -@c FIXME: un-geekify -@item Music lists are allowed at toplevel, and are handled by -@code{default-toplevel-music-handler}. Similarly, a @code{score} block -at toplevel is handled by @code{default-toplevel-score-handler} an a -@code{book} at toplevel is handled by @code{default-toplevel-book-handler}. - -These default handlers have the following effect. A Music list at -toplevel is encapsulated in a @code{score} block, and a @code{score} -block at toplevel is encapsulated in a @code{book} block. A -@code{book} block at toplevel generates printed output. +@item Music lists are allowed at toplevel. @example \header @{ title = "The Title" @} @@ -77,6 +70,22 @@ is the same as @} @end example +These toplevel forms are handled by +@code{default-toplevel-music-handler}. Similarly, a @code{score} +block at toplevel is handled by @code{default-toplevel-score-handler} +an a @code{book} at toplevel is handled by +@code{default-toplevel-book-handler}. + +@ignore + +@c FIXME: un-geekify +These default handlers have the following effect. A Music list at +toplevel is encapsulated in a @code{score} block, and a @code{score} +block at toplevel is encapsulated in a @code{book} block. A +@code{book} block at toplevel generates printed output. +@end ignore + + @item Start pitch for @code{relative} music is optional for music lists. The default value is one octave below middle C. diff --git a/Documentation/user/invoking.itexi b/Documentation/user/invoking.itexi index 33acbece80..a66b62f6ed 100644 --- a/Documentation/user/invoking.itexi +++ b/Documentation/user/invoking.itexi @@ -259,10 +259,9 @@ information. @c @c Output format for sheet music. Choices are @code{tex} (for @TeX{} -output, to be processed with plain @TeX{}, or through @code{lilypond}), +output, to be processed with La@TeX{}, or through @code{lilypond}), @code{pdftex} for PDF@TeX{} input, @code{ps} (for PostScript), -@code{scm} (for a Scheme dump), @code{sk} (for Sketch) and @code{as} -(for ASCII-art). +@code{scm} (for a Scheme dump), @code{sk} (for Sketch). @strong{This option is only for developers}. Only the @TeX{} output of these is usable for real work. @@ -270,7 +269,6 @@ these is usable for real work. @cindex output format, setting @cindex Sketch output -@cindex ASCII-art output @cindex PDFTeX output @cindex PostScript output @cindex Scheme dump @@ -291,8 +289,8 @@ will be generated. Set the default output file to @var{FILE}. @item -s,--safe -Disallow untrusted @code{\include} directives, in-line -Scheme evaluation, backslashes in @TeX{}, code. +Disallow untrusted @code{\include} directives, limit available in-line +Scheme function, disable backslashes in @TeX{}, code. @item -v,--version Show version information. diff --git a/Documentation/user/programming-interface.itely b/Documentation/user/programming-interface.itely index 7b08550748..05044a9321 100644 --- a/Documentation/user/programming-interface.itely +++ b/Documentation/user/programming-interface.itely @@ -85,6 +85,9 @@ written as \score @{ #(ly:export (make-sequential-music newLa)) @} @end example +@refbugs + +Mixing Scheme and lily identifiers is not possible with @code{--safe}. @node Internal music representation @appendixsubsec Internal music representation diff --git a/lily/grob.cc b/lily/grob.cc index b1e6324a94..b32b83a201 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -36,7 +36,6 @@ remove dynamic_cast and put this code into respective subclass. */ -//#define HASHING_FOR_MUTABLE_PROPS #define HASH_SIZE 3 #define INFINITY_MSG "Infinity or NaN encountered" @@ -60,9 +59,6 @@ Grob::Grob (SCM basicprops) smobify_self (); -#ifdef HASHING_FOR_MUTABLE_PROPS - mutable_property_alist_ = scm_c_make_hash_table (HASH_SIZE); -#endif SCM meta = get_property ("meta"); if (ly_c_pair_p (meta)) @@ -138,10 +134,6 @@ Grob::Grob (Grob const&s) pscore_ = 0; smobify_self (); - -#ifdef HASHING_FOR_MUTABLE_PROPS - mutable_property_alist_ = scm_c_make_hash_table (HASH_SIZE); -#endif } Grob::~Grob () @@ -233,37 +225,31 @@ Grob::get_uncached_stencil ()const if (ly_c_procedure_p (proc)) mol = scm_apply_0 (proc, scm_list_n (this->self_scm (), SCM_UNDEFINED)); - Stencil *m = unsmob_stencil (mol); - - if (unsmob_stencil (mol)) - { - SCM origin = ly_symbol2scm ("no-origin"); + if (Stencil *m = unsmob_stencil (mol)) + { + if (to_boolean (get_property ("transparent"))) + mol = Stencil (m->extent_box (), SCM_EOL).smobbed_copy (); + else + { + SCM origin = ly_symbol2scm ("no-origin"); - if (store_locations_global_b) - { - SCM cause = get_property ("cause"); - if (Music*m = unsmob_music (cause)) - { - SCM music_origin = m->get_property ("origin"); - if (unsmob_input (music_origin)) - origin = music_origin; - } + if (store_locations_global_b) + { + SCM cause = get_property ("cause"); + if (Music*m = unsmob_music (cause)) + { + SCM music_origin = m->get_property ("origin"); + if (unsmob_input (music_origin)) + origin = music_origin; + } + } + + // ugr. + mol = Stencil (m->extent_box (), + scm_list_n (origin, m->expr (), SCM_UNDEFINED) + ). smobbed_copy (); } - - // ugr. - - mol = Stencil (m->extent_box (), - scm_list_n (origin, m->expr (), SCM_UNDEFINED) - ). smobbed_copy (); - - m = unsmob_stencil (mol); - } - - /* - transparent retains dimensions of element. - */ - if (m && to_boolean (get_property ("transparent"))) - mol = Stencil (m->extent_box (), SCM_EOL).smobbed_copy (); + } return mol; } @@ -356,9 +342,6 @@ Grob::suicide () if (!live ()) return; -#if 0 // see below. - String nm = name (); -#endif mutable_property_alist_ = SCM_EOL; immutable_property_alist_ = SCM_EOL; @@ -371,19 +354,6 @@ Grob::suicide () dim_cache_[a].offset_callbacks_ = SCM_EOL; dim_cache_[a].offsets_left_ = 0; } - -#if 0 - /* - This can make debugging a little easier: we can still know what - the object used to be. However, since all its links have been - broken, it's usually more convenient to set a conditional - breakpoint in GDB before the property lists are wiped. - */ - mutable_property_alist_ = scm_acons (ly_symbol2scm ("name"), - scm_makfrom0str (nm.to_str0()), - mutable_property_alist_ - ); -#endif } void diff --git a/lily/include/coherent-ligature-engraver.hh b/lily/include/coherent-ligature-engraver.hh index b9ec709ecf..afa6f6bd17 100644 --- a/lily/include/coherent-ligature-engraver.hh +++ b/lily/include/coherent-ligature-engraver.hh @@ -13,7 +13,6 @@ class Coherent_ligature_engraver : public Ligature_engraver { - public: TRANSLATOR_DECLARATIONS(Coherent_ligature_engraver); @@ -23,7 +22,6 @@ protected: virtual void typeset_ligature (Spanner *ligature, Array primitives); virtual void get_set_column (Item *, Paper_column *); - private: void collect_accidentals (Spanner *, Array); }; diff --git a/lily/include/lily-guile.hh b/lily/include/lily-guile.hh index cf0a60f691..1241e34cff 100644 --- a/lily/include/lily-guile.hh +++ b/lily/include/lily-guile.hh @@ -137,6 +137,9 @@ inline SCM ly_symbol2scm(char const* x) { return scm_str2symbol((x)); } extern SCM global_lily_module; +/* + TODO: rename me to ly_c_lily_module_eval + */ #define ly_scheme_function(x) ({static SCM cached; \ SCM value = cached; /* We store this one locally, since G++ -O2 fucks up else */ \ if ( __builtin_constant_p ((x)))\ diff --git a/lily/include/parse-scm.hh b/lily/include/parse-scm.hh index b53fe8949c..79ef343ebf 100644 --- a/lily/include/parse-scm.hh +++ b/lily/include/parse-scm.hh @@ -20,6 +20,7 @@ struct Parse_start char const* str; int nchars; Input start_location_; + bool safe_; }; SCM catch_protected_parse_body (void *); diff --git a/lily/music-output-def.cc b/lily/music-output-def.cc index d55ebd92a8..54b9b33cab 100644 --- a/lily/music-output-def.cc +++ b/lily/music-output-def.cc @@ -42,7 +42,7 @@ Music_output_def::Music_output_def (Music_output_def const &s) translator_tab_ = new Scheme_hash_table (*s.translator_tab_); scm_gc_unprotect_object (translator_tab_->self_scm ()); - scope_= ly_make_anonymous_module (safe_global_b); + scope_= ly_make_anonymous_module (false); if (is_module (s.scope_)) ly_import_module (scope_, s.scope_); } diff --git a/lily/my-lily-lexer.cc b/lily/my-lily-lexer.cc index 7fa4569c05..f7a8eabae9 100644 --- a/lily/my-lily-lexer.cc +++ b/lily/my-lily-lexer.cc @@ -104,7 +104,7 @@ My_lily_lexer::My_lily_lexer (Sources *sources) error_level_ = 0; main_input_b_ = false; - add_scope (ly_make_anonymous_module (safe_global_b)); + add_scope (ly_make_anonymous_module (false)); } My_lily_lexer::My_lily_lexer (My_lily_lexer const &src) diff --git a/lily/my-lily-parser.cc b/lily/my-lily-parser.cc index 68e864d5c8..af660e4646 100644 --- a/lily/my-lily-parser.cc +++ b/lily/my-lily-parser.cc @@ -36,7 +36,7 @@ My_lily_parser::My_lily_parser (Sources *sources) last_beam_start_ = SCM_EOL; header_ = SCM_EOL; - header_ = ly_make_anonymous_module (safe_global_b); + header_ = ly_make_anonymous_module (false); smobify_self (); } @@ -176,12 +176,13 @@ My_lily_parser::here_input () const Parsing looks ahead , so we really want the previous location of the lexer, not lexer_->here_input (). */ + /* Actually, that gets very icky when there are white space, because the line-numbers are all wrong. Let's try the character before - the current token. That gets the right result for - note/duration stuff, but doesn't mess up for errors in the 1st token of the line. - + the current token. That gets the right result for note/duration + stuff, but doesn't mess up for errors in the 1st token of the + line. */ Input hi (lexer_->here_input ()); @@ -212,9 +213,9 @@ LY_DEFINE (ly_set_point_and_click, "ly:set-point-and-click", 1, 0, 0, /* UGH. */ SCM val = SCM_BOOL_F; if (ly_symbol2scm ("line-column") == what) - val = scm_c_eval_string ("line-column-location"); + val = ly_scheme_function ("line-column-location"); else if (what == ly_symbol2scm ("line")) - val = scm_c_eval_string ("line-location"); + val = ly_scheme_function ("line-location"); scm_module_define (global_lily_module, ly_symbol2scm ("point-and-click"), val); diff --git a/lily/paper-outputter.cc b/lily/paper-outputter.cc index 38ff508b5f..94bff9eaed 100644 --- a/lily/paper-outputter.cc +++ b/lily/paper-outputter.cc @@ -38,15 +38,8 @@ Paper_outputter::Paper_outputter (String filename) file_ = scm_open_file (scm_makfrom0str (filename.to_str0 ()), scm_makfrom0str ("w")); - /* - UGH. -> global variable. - */ - if (safe_global_b) - scm_define (ly_symbol2scm ("safe-mode?"), SCM_BOOL_T); - String module_name = "scm output-" + output_format_global; output_module_ = scm_c_resolve_module (module_name.to_str0 ()); - } Paper_outputter::~Paper_outputter () diff --git a/lily/parse-scm.cc b/lily/parse-scm.cc index 03d1df4ff1..8fd3cb3ab9 100644 --- a/lily/parse-scm.cc +++ b/lily/parse-scm.cc @@ -29,6 +29,10 @@ internal_ly_parse_scm (Parse_start * ps) /* Read expression from port */ if (!SCM_EOF_OBJECT_P (form = scm_read (port))) { + if (ps->safe_) + answer = scm_eval (form, + scm_call_0 (ly_scheme_function ("make-safe-lilypond-module"))); + else answer = scm_primitive_eval (form); } @@ -51,13 +55,7 @@ SCM catch_protected_parse_body (void *p) { Parse_start *ps = (Parse_start*) p; - return internal_ly_parse_scm (ps); -} - -SCM -safe_catch_protected_parse_body (void *p) -{ - Parse_start *ps = (Parse_start*) p; + return internal_ly_parse_scm (ps); } @@ -111,7 +109,8 @@ ly_parse_scm (char const* s, int *n, Input i, bool safe) Parse_start ps ; ps.str = s; ps.start_location_ = i; - + ps.safe_ = safe; + SCM ans = parse_protect_global ? protected_ly_parse_scm (&ps) : internal_ly_parse_scm (&ps); *n = ps.nchars; diff --git a/lily/scm-option.cc b/lily/scm-option.cc index e7d5a31ec1..5a7c6cee19 100644 --- a/lily/scm-option.cc +++ b/lily/scm-option.cc @@ -148,7 +148,10 @@ LY_DEFINE (ly_get_option, "ly:get-option", 1, 0, 0, (SCM var), "\n") { SCM o = SCM_UNSPECIFIED; - if (var == ly_symbol2scm ("old-relative-used")) + + if (var == ly_symbol2scm ("safe")) // heavily used; put in front. + o = ly_bool2scm (safe_global_b); + else if (var == ly_symbol2scm ("old-relative-used")) o = ly_bool2scm (lily_1_8_compatibility_used); else if (var == ly_symbol2scm ("old-relative")) o = ly_bool2scm (lily_1_8_relative); diff --git a/lily/score.cc b/lily/score.cc index a917614b26..262baa7155 100644 --- a/lily/score.cc +++ b/lily/score.cc @@ -86,7 +86,7 @@ Score::Score (Score const &s) for (int i = 0; i < s.defs_.size (); i++) defs_.push (s.defs_[i]->clone ()); - header_ = ly_make_anonymous_module (safe_global_b); + header_ = ly_make_anonymous_module (false); if (is_module (s.header_)) ly_import_module (header_, s.header_); } diff --git a/scm/lily.scm b/scm/lily.scm index bf2ed056b4..58c3a603e0 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -95,10 +95,6 @@ (define-public default-script-alist '()) -(define-public safe-mode? #f) - - - ;; parser stuff. (define-public (print-music-as-book parser music) diff --git a/scm/output-pdftex.scm b/scm/output-pdftex.scm index d6d3e44ce3..5d5702e01f 100644 --- a/scm/output-pdftex.scm +++ b/scm/output-pdftex.scm @@ -173,8 +173,11 @@ ;; FIXME: explain ploblem: need to do something to make this really safe. (define (output-tex-string s) - (if safe-mode? - (regexp-substitute/global #f "\\\\" s 'pre "$\\backslash$" 'post) + (if (ly:get-option 'safe) + (regexp-substitute/global #f "\\\\" + (regexp-substitute/global #f "\\([{}]\\)" s 'pre "\\1" 'post) + 'pre "$\\backslash$" 'post) + s)) (define (lily-def key val) diff --git a/scm/output-tex.scm b/scm/output-tex.scm index 51453320e4..4c0800a25b 100644 --- a/scm/output-tex.scm +++ b/scm/output-tex.scm @@ -256,11 +256,13 @@ "\\def\\lilypondtagline{Engraved by LilyPond (version " (lilypond-version)")}\n")) -;; FIXME: explain ploblem: need to do something to make this really safe. (define (output-tex-string s) - (if safe-mode? - (regexp-substitute/global #f "\\\\" s 'pre "$\\backslash$" 'post) - s)) + (if (ly:get-option 'safe) + (regexp-substitute/global #f "\\\\" + (regexp-substitute/global #f "([{}])" "bla{}" 'pre "\\" 1 'post ) + 'pre "$\\backslash$" 'post) + + s)) (define (lily-def key val) (let ((tex-key diff --git a/scm/safe-lily.scm b/scm/safe-lily.scm new file mode 100644 index 0000000000..ea9215c5d1 --- /dev/null +++ b/scm/safe-lily.scm @@ -0,0 +1,294 @@ +(define safe-objects + + (map + (lambda (sym) + (cons sym (primitive-eval sym))) + '(ly:add-interface + ly:add-moment + ly:all-grob-interfaces + ly:bracket + ly:context-find + ly:context-id + ly:context-name + ly:context-parent + ly:context-property + ly:context-property-where-defined + ly:context-pushpop-property + ly:context-set-property! + ly:context-unset-property + ly:context? + ly:dimension? + ly:dir? + ly:div-moment + ly:duration-dot-count + ly:duration-factor + ly:duration-log + ly:durationstring + ly:option-usage + ly:output-def-clone + ly:output-def-scope + ly:output-description + ly:page-header-lines-footer-stencil + ly:page-paper-lines + ly:page? + ly:paper-book? + ly:paper-def? + ly:paper-get-font + ly:paper-get-number + ly:paper-line-break-score + ly:paper-line-height + ly:paper-line-number + ly:paper-line-stencil + ly:paper-line? + ly:paper-lookup + ly:parse-string + ly:parser-parse-string + ly:parser-print-book + ly:parser-print-score + ly:pitch-alteration + ly:pitch-diff + ly:pitch-notename + ly:pitch-octave + ly:pitch-quartertones + ly:pitch-semitones + ly:pitch-steps + ly:pitch-transpose + ly:pitchhash-table + default-chord-modifier-list + sequential-music-to-chord-exceptions + make-music + make-articulation + make-event-chord + make-penalty-music + make-span-event + set-start-grace-properties + set-stop-grace-properties + set-default-paper-size + set-part-combine-listener + context-spec-music + make-voice-props-revert + make-voice-props-set + chord-name->german-markup + note-name->german-markup + default-toplevel-music-handler + default-toplevel-book-handler + default-toplevel-score-handler + + Accidental_interface::after_line_breaking + Accidental_interface::print + Ambitus::print + Arpeggio::print + Arpeggio::brew_chord_bracket + Arpeggio::width_callback + Axis_group_interface::group_extent_callback + Bar_line::before_line_breaking + Bar_line::get_staff_bar_size + Bar_line::print + Beam::after_line_breaking + Beam::before_line_breaking + Beam::check_concave + Beam::least_squares + Beam::print + Beam::quanting + Beam::shift_region_to_valid + Beam::slope_damping + Beam::space_function + Break_align_interface::alignment_callback + Breathing_sign::offset_callback + Chord_name::after_line_breaking + Clef::before_line_breaking + Clef::print + Cluster::print + Cluster_beacon::height + Custos::print + Dot_column::side_position + Dots::print + Hairpin::print + Hara_kiri_group_spanner::force_hara_kiri_callback + Hara_kiri_group_spanner::y_extent + Horizontal_bracket::print + Hyphen_spanner::print + Hyphen_spanner::set_spacing_rods + Key_signature_interface::print + Line_spanner::after_line_breaking + Line_spanner::print + Lyric_extender::print + Measure_grouping::print + Mensural_ligature::brew_ligature_primitive + Mensural_ligature::print + Multi_measure_rest::percent + Multi_measure_rest::print + Multi_measure_rest::set_spacing_rods + Note_head::extent + Note_head::print + Note_head::brew_ez_stencil + Ottava_bracket::print + Paper_column::before_line_breaking + Paper_column::print + Percent_repeat_item_interface::beat_slash + Percent_repeat_item_interface::double_percent + Piano_pedal_bracket::print + Rest::after_line_breaking + Rest::extent_callback + Rest::polyphonic_offset_callback + Rest::print + Script_column::before_line_breaking + Script_interface::before_line_breaking + Script_interface::print + Self_alignment_interface::aligned_on_parent + Self_alignment_interface::aligned_on_self + Self_alignment_interface::centered_on_other_axis_parent + Self_alignment_interface::centered_on_parent + Separating_group_spanner::set_spacing_rods + Side_position_interface::aligned_on_support_refpoints + Side_position_interface::aligned_side + Slur::after_line_breaking + Slur::height + Slur::print + Spacing_spanner::set_springs + Span_bar::before_line_breaking + Span_bar::get_bar_size + Span_bar::print + Span_bar::width_callback + Spanner::set_spacing_rods + Staff_symbol::print + Staff_symbol_referencer::callback + Stem::before_line_breaking + Stem::dim_callback + Stem::height + Stem::off_callback + Stem::print + Stem_tremolo::height + Stem_tremolo::print + Sustain_pedal::print + System_start_delimiter::after_line_breaking + System_start_delimiter::print + Text_item::print + Text_spanner::print + Tie::print + Tie_column::after_line_breaking + Time_signature::print + Tuplet_bracket::after_line_breaking + Tuplet_bracket::before_line_breaking + Tuplet_bracket::print + Vaticana_ligature::brew_ligature_primitive + Vaticana_ligature::print + Volta_bracket_interface::print + + + + + ))) + +(define-public (make-safe-lilypond-module) + (let* + ((m (make-safe-module))) + (for-each + (lambda (p) (module-define! m (car p) (cdr p))) + safe-objects) + m)) +