2004-05-09 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * 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 <hanwen@xs4all.nl>
@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.
@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)
@}
@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" @}
@}
@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.
@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.
@cindex output format, setting
@cindex Sketch output
-@cindex ASCII-art output
@cindex PDFTeX output
@cindex PostScript output
@cindex Scheme dump
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.
\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
subclass.
*/
-//#define HASHING_FOR_MUTABLE_PROPS
#define HASH_SIZE 3
#define INFINITY_MSG "Infinity or NaN encountered"
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))
pscore_ = 0;
smobify_self ();
-
-#ifdef HASHING_FOR_MUTABLE_PROPS
- mutable_property_alist_ = scm_c_make_hash_table (HASH_SIZE);
-#endif
}
Grob::~Grob ()
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;
}
if (!live ())
return;
-#if 0 // see below.
- String nm = name ();
-#endif
mutable_property_alist_ = SCM_EOL;
immutable_property_alist_ = SCM_EOL;
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
class Coherent_ligature_engraver : public Ligature_engraver
{
-
public:
TRANSLATOR_DECLARATIONS(Coherent_ligature_engraver);
virtual void typeset_ligature (Spanner *ligature,
Array<Grob_info> primitives);
virtual void get_set_column (Item *, Paper_column *);
-
private:
void collect_accidentals (Spanner *, Array<Grob_info>);
};
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)))\
char const* str;
int nchars;
Input start_location_;
+ bool safe_;
};
SCM catch_protected_parse_body (void *);
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_);
}
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)
last_beam_start_ = SCM_EOL;
header_ = SCM_EOL;
- header_ = ly_make_anonymous_module (safe_global_b);
+ header_ = ly_make_anonymous_module (false);
smobify_self ();
}
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 ());
/* 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);
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 ()
/* 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);
}
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);
}
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;
"\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);
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_);
}
(define-public default-script-alist '())
-(define-public safe-mode? #f)
-
-
-
;; parser stuff.
(define-public (print-music-as-book parser music)
;; 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)
"\\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
--- /dev/null
+(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:duration<?
+ ly:duration?
+ ly:export
+ ly:find-glyph-by-name
+ ly:font-design-size
+ ly:font-encoding-alist
+ ly:font-filename
+ ly:font-magnification
+ ly:font-metric?
+ ly:font-name
+ ly:format-output
+ ly:get-all-function-documentation
+ ly:get-all-translators
+ ly:get-default-font
+ ly:get-glyph
+ ly:get-option
+ ly:grob-alist-chain
+ ly:grob-extent
+ ly:grob-original
+ ly:grob-paper
+ ly:grob-parent
+ ly:grob-pq-less?
+ ly:grob-property
+ ly:grob-script-priority-less
+ ly:grob-set-property!
+ ly:grob-staff-position
+ ly:grob-suicide
+ ly:grob-system
+ ly:grob-translate-axis!
+ ly:grob?
+ ly:input-location
+ ly:input-location?
+ ly:input-message
+ ly:intlog2
+ ly:item-break-dir
+ ly:item?
+ ly:iterator?
+ ly:make-bare-music
+ ly:make-duration
+ ly:make-moment
+ ly:make-music-function
+ ly:make-pitch
+ ly:make-stencil
+ ly:moment<?
+ ly:moment?
+ ly:mul-moment
+ ly:music-compress
+ ly:music-deep-copy
+ ly:music-duration-compress
+ ly:music-duration-length
+ ly:music-length
+ ly:music-list?
+ ly:music-mutable-properties
+ ly:music-name
+ ly:music-property
+ ly:music-scorify
+ ly:music-set-property!
+ ly:music-transpose
+ ly:music?
+ ly:my-lily-parser?
+ ly:number->string
+ 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:pitch<?
+ ly:pitch?
+ ly:ragged-page-breaks
+ ly:round-filled-box
+ ly:run-translator
+ ly:set-option
+ ly:score-bookify
+ ly:set-point-and-click
+ ly:spanner-broken-into
+ ly:spanner-get-bound
+ ly:spanner?
+ ly:stencil-add
+ ly:stencil-align-to!
+ ly:stencil-combine-at-edge
+ ly:stencil-expr
+ ly:stencil-extent
+ ly:stencil-moved-to-edge
+ ly:stencil-set-extent!
+ ly:stencil-translate
+ ly:stencil-translate-axis
+ ly:stencil?
+ ly:text-dimension
+ ly:translator-description
+ ly:translator-name
+ ly:translator?
+ ly:transpose-key-alist
+ ly:unit
+ ly:version
+ ly:warn
+
+ ;; need these for parsing init files:
+ ;; todo: should have a macro define-safe-public
+ DOUBLE-FLAT
+ THREE-Q-FLAT
+ FLAT
+ SEMI-FLAT
+ NATURAL
+ SEMI-SHARP
+ SHARP
+ THREE-Q-SHARP
+ DOUBLE-SHARP
+ SEMI-TONE
+ START
+ STOP
+ alist->hash-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))
+