In the 1990ies it was well-known that you could crash many programs by
giving them garbage (a.k.a. "random") input. This technique uncovered
many bugs that would also occur on valid (but rarely seen) input.
Later this technique evolved into "fuzzing".

It applies to groff too. See:

$ groff --version
GNU groff version 1.24.0.rc2
...
GNU grops (groff) version 1.24.0.rc2
GNU troff (groff) version 1.24.0.rc2

$ wget https://ftp.gnu.org/gnu/sed/sed-4.8.tar.xz

$ groff -Tpdf sed-4.8.tar.xz  > /dev/null
...
troff:sed-4.8.tar.xz:4026: error: cannot format glyph: no current font
troff:sed-4.8.tar.xz:4026: error: ignoring invalid numeric expression starting 
with character code 225
groff: error: troff: Segmentation fault (core dumped)

Oops: troff dumped core! Let's see where:

$ gdb /arch/x86_64-linux-gnu/gnu-inst-groff/1.24.0-rc2/bin/troff 
/var/lib/apport/coredump/core._arch_x86_64-linux-gnu_gnu-inst-groff_1_24_0-rc2_bin_troff.1000.1da7a7b2-b09b-458f-8578-69b57283288c.1409721.176848446

Core was generated by `troff -Tpdf sed-4.8.tar.xz'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000000000044704d in font_info::get_tfont (this=0x191, fs=..., height=0, 
slant=0, fontno=-1) at src/roff/troff/node.cpp:312
312       if (0 /* nullptr */ == last_tfont
(gdb) where
#0  0x000000000044704d in font_info::get_tfont (this=0x191, fs=..., height=0, 
slant=0, fontno=-1) at src/roff/troff/node.cpp:312
#1  0x0000000000452377 in device_extension_node::device_extension_node 
(this=0x14ded180, m=..., b=false) at src/roff/troff/node.cpp:4369
#2  0x000000000042fcb2 in do_device_extension () at 
src/roff/troff/input.cpp:6787
#3  0x0000000000423635 in token::next (this=0x4b4b40 <tok>) at 
src/roff/troff/input.cpp:2675
#4  0x0000000000425d28 in process_input_stack () at 
src/roff/troff/input.cpp:3556
#5  0x00000000004376d3 in process_input_file (name=0x7ffde98a36d3 
"sed-4.8.tar.xz") at src/roff/troff/input.cpp:9731
#6  0x00000000004389ba in main (argc=3, argv=0x7ffde98a2ce8) at 
src/roff/troff/input.cpp:10103
(gdb) print this
$4 = (font_info * const) 0x191
(gdb) up
#1  0x0000000000452377 in device_extension_node::device_extension_node 
(this=0x14ded180, m=..., b=false) at src/roff/troff/node.cpp:4369
4369      tf = font_table[fontno]->get_tfont(fs, char_height, char_slant,
(gdb) print font_table
$5 = (font_info **) 0x14cef9c0
(gdb) print fontno
$6 = -1
(gdb) print this
$7 = (device_extension_node * const) 0x14ded180
(gdb) print *this
$8 = {<node> = {_vptr.node = 0x47dc80 <vtable for device_extension_node+16>, 
next = 0x0, last = 0x0, state = 0x0, push_state = 0x0, 
    div_nest_level = 0, is_special = true}, mac = {<request_or_macro> = 
{<object> = {_vptr.object = 0x479218 <vtable for macro+16>, 
        refcount = 0}, <No data fields>}, filename = 0x14d3d490 
"sed-4.8.tar.xz", lineno = 4026, len = 233, is_empty_macro = false, 
    is_a_diversion = false, is_a_string = true, p = 0x14de14e0}, tf = 
0x59eeabe12b567b76, gcol = 0x367076eedc716e23, fcol = 0x34673043c6e9ad4c, 
  lacks_command_prefix = false}
(gdb) print curenv
$9 = (environment *) 0x14b01e10
(gdb) print *curenv
$10 = {is_dummy_env = false, prev_line_length = {n = 468000}, line_length = {n 
= 468000}, prev_title_length = {n = 468000}, title_length = {
    n = 468000}, prev_size = {p = 10000}, size = {p = 4000}, requested_size = 
4000, prev_requested_size = 10000, char_height = 0, 
  char_slant = 0, prev_fontno = 24, fontno = 2, prev_family = 0x14dd5170, 
family = 0x14dd1190, space_size = 12, sentence_space_size = 12, 
  adjust_mode = 1, is_filling = true, was_line_interrupted = false, 
was_previous_line_interrupted = 0, centered_line_count = 0, 
  right_aligned_line_count = 0, prev_vertical_spacing = {n = 12000}, 
vertical_spacing = {n = 12000}, prev_post_vertical_spacing = {n = 0}, 
  post_vertical_spacing = {n = 0}, prev_line_spacing = 1, line_spacing = 1, 
prev_indent = {n = 0}, indent = {n = 0}, temporary_indent = {
    n = 0}, have_temporary_indent = false, saved_indent = {n = 0}, 
target_text_length = {n = 468000}, pre_underline_fontno = 0, 
  underlined_line_count = 0, underline_spaces = false, input_trap = {s = 0x0}, 
input_trap_count = -1, continued_input_trap = false, 
  line = 0x14de15a0, prev_text_length = {n = 468000}, width_total = {n = 
181333}, space_total = 9, input_line_start = {n = 39999}, 
  tab_contents = 0x0, tab_width = {n = 0}, tab_distance = {n = 0}, 
using_line_tabs = false, current_tab = TAB_NONE, leader_node = 0x0, 
  tab_char = 0x0, leader_char = 0x14af3110, has_current_field = false, 
field_distance = {n = 0}, pre_field_width = {n = 0}, field_spaces = 0, 
  tab_field_spaces = 347148832, tab_precedes_field = false, is_discarding = 
false, is_spreading = false, margin_character_flags = 0 '\000', 
  margin_character_node = 0x0, margin_character_distance = {n = 10000}, 
numbering_nodes = 0x0, line_number_digit_width = {n = 0}, 
  number_text_separation = 1, line_number_indent = 0, line_number_multiple = 1, 
no_number_count = 0, hyphenation_mode = 4, 
  hyphenation_mode_default = 4, hyphen_line_count = 0, hyphen_line_max = -1, 
hyphenation_space = {n = 0}, hyphenation_margin = {n = 0}, 
  composite = false, pending_lines = 0x0, stroke_color = 0x4b8660 
<default_color>, prev_stroke_color = 0x4b8660 <default_color>, 
  fill_color = 0x14b42900, prev_fill_color = 0x4b8660 <default_color>, 
control_character = 46 '.', no_break_control_character = 39 '\'', 
  seen_space = true, seen_eol = false, suppress_next_eol = false, seen_break = 
true, tabs = {initial_list = 0x0, repeated_list = 0x14b01fc0}, 
  name = {s = 0x14aa95e2 "0"}, hyphen_indicator_char = 0x0}

So, it seems like the expression env_resolve_font(curenv) (node.cpp:4368)
can return -1, whereas the code is not prepared for this case.

Bruno




Reply via email to