[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Incorrect sub-char-table length can cause segfault

From: Gareth Jones
Subject: Incorrect sub-char-table length can cause segfault
Date: 03 Apr 2003 18:50:33 +0100
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

In GNU Emacs 21.3.1 (i686-pc-linux-gnu, X toolkit, Xaw3d scroll bars)
 of 2003-03-28 on gwa3
Important settings:
  locale-coding-system: iso-latin-1
  default-enable-multibyte-characters: t

I think I've reported this bug previously in Emacs 21.2 or 21.1, but
not in as much detail.  Anyway, it is still present in 21.3.

The following will usually, though not always, cause Emacs to

  (setq print-circle t)
  (setq test-str " | ")
  (setq test-syntax-table (make-syntax-table))
  (put-text-property 0 1 'syntax-table test-syntax-table test-str)
  (put-text-property 2 3 'syntax-table test-syntax-table test-str)
  (setq test-str-as-string (prin1-to-string test-str)))
; Now this will usually cause a segfault or an infinite loop, if not,
;  try running it again
(read test-str-as-string)

This means that Emacs can crash when I use `session-save-session' if
there is text in the kill ring with the syntax-table property set.
cperl-mode, among others, does this.  Although the bug only appears if
print-circle is t, I think the fundamental problem is not directly
related to the printing or reading code.  I explain my reasoning

Consider the make_sub_char_table function at alloc.c:2394: it creates
a vector with SUB_CHAR_TABLE_STANDARD_SLOTS elements.  Similarly, when
read with `read1' a sub-char-table clearly has
SUB_CHAR_TABLE_STANDARD_SLOTS elements (lread.c:1855)

Now in the aref function (data.c:1771) a sub-char-table satisfies
CHAR_TABLE_P.  So if `idxval' is greater than
SUB_CHAR_TABLE_STANDARD_SLOTS (= 130) but less than
CHAR_TABLE_ORDINARY_SLOTS (= 384) then line 1783 causes a read outside
the allocated memory.

Furthermore, the length function (fns.c:143) returns a length of
MAX_CHAR for a sub-char-table.

Bearing this in mind, look at substitute_object_recurse
(lread.c:2477): this will recurse down a char-table and when it finds
a sub-char-table it will get its length using Flength (MAX_CHAR) and
then use Faref to read at every index from 0 up to MAX_CHAR.  This
often causes a segfault.  It doesn't always, because often the
memory read is valid so the problem can be slightly intermittent.

It seems to me that any index less than the length given by `length'
should be a valid argument to `aref' and `aset' and the bug is that
this assumption is not valid.  One way to fix the bug is to alter
`length', as shown below.

diff -c /opt/src/emacs-21.2/src/fns.c /mnt/dosd/src/emacs-21.2/src/fns.c
*** /opt/src/emacs-21.2/src/fns.c       Sat Sep  1 10:21:16 2001
--- /mnt/dosd/src/emacs-21.2/src/fns.c  Wed Jul  3 12:12:25 2002
*** 140,145 ****
--- 140,147 ----
      XSETFASTINT (val, XSTRING (sequence)->size);
    else if (VECTORP (sequence))
      XSETFASTINT (val, XVECTOR (sequence)->size);
+   else if (SUB_CHAR_TABLE_P (sequence))
    else if (CHAR_TABLE_P (sequence))
    else if (BOOL_VECTOR_P (sequence))

Diff finished at Thu Apr  3 17:33:59

Gareth Jones

reply via email to

[Prev in Thread] Current Thread [Next in Thread]