diff options
| author | Paul Eggert | 2013-11-20 22:46:59 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-11-20 22:46:59 -0800 |
| commit | 75360f19c3994ab7a532124b7f5eb92bfe7c82ed (patch) | |
| tree | ed6a415b319a37144d63bdfe967daff766f4e044 /src | |
| parent | d1a6bccc995f7e1e9d22a386e1aac0d7c888ff18 (diff) | |
| download | emacs-75360f19c3994ab7a532124b7f5eb92bfe7c82ed.tar.gz emacs-75360f19c3994ab7a532124b7f5eb92bfe7c82ed.zip | |
Fix recently introduced bool vector overrun.
This was due to an optimization that went awry.
Reported by Glenn Morris in
<http://lists.gnu.org/archive/html/emacs-devel/2013-11/msg00622.html>.
* alloc.c (make_uninit_bool_vector): Don't allocate a dummy word
for empty vectors, undoing the 2013-11-18 change.
* data.c (bool_vector_binop_driver): Rely on this.
Fix bug that occasionally overran the destination.
* lisp.h (struct Lisp_Bool_vector): Document this.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 12 | ||||
| -rw-r--r-- | src/alloc.c | 9 | ||||
| -rw-r--r-- | src/data.c | 50 | ||||
| -rw-r--r-- | src/lisp.h | 2 |
4 files changed, 44 insertions, 29 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index e0ac7f298c7..925f6389bf8 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,15 @@ | |||
| 1 | 2013-11-21 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix recently introduced bool vector overrun. | ||
| 4 | This was due to an optimization that went awry. | ||
| 5 | Reported by Glenn Morris in | ||
| 6 | <http://lists.gnu.org/archive/html/emacs-devel/2013-11/msg00622.html>. | ||
| 7 | * alloc.c (make_uninit_bool_vector): Don't allocate a dummy word | ||
| 8 | for empty vectors, undoing the 2013-11-18 change. | ||
| 9 | * data.c (bool_vector_binop_driver): Rely on this. | ||
| 10 | Fix bug that occasionally overran the destination. | ||
| 11 | * lisp.h (struct Lisp_Bool_vector): Document this. | ||
| 12 | |||
| 1 | 2013-11-20 Jan Djärv <jan.h.d@swipnet.se> | 13 | 2013-11-20 Jan Djärv <jan.h.d@swipnet.se> |
| 2 | 14 | ||
| 3 | * nsterm.m (init, run, stop:): Enable again. stop calls super stop | 15 | * nsterm.m (init, run, stop:): Enable again. stop calls super stop |
diff --git a/src/alloc.c b/src/alloc.c index 7c560fd0f0d..283bc613c82 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -2066,8 +2066,7 @@ Lisp_Object | |||
| 2066 | make_uninit_bool_vector (EMACS_INT nbits) | 2066 | make_uninit_bool_vector (EMACS_INT nbits) |
| 2067 | { | 2067 | { |
| 2068 | Lisp_Object val; | 2068 | Lisp_Object val; |
| 2069 | EMACS_INT words0 = bool_vector_words (nbits); | 2069 | EMACS_INT words = bool_vector_words (nbits); |
| 2070 | EMACS_INT words = words0 + !words0; /* Allocate at least one word. */ | ||
| 2071 | EMACS_INT word_bytes = words * sizeof (bits_word); | 2070 | EMACS_INT word_bytes = words * sizeof (bits_word); |
| 2072 | EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes | 2071 | EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes |
| 2073 | + word_size - 1) | 2072 | + word_size - 1) |
| @@ -2078,9 +2077,9 @@ make_uninit_bool_vector (EMACS_INT nbits) | |||
| 2078 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); | 2077 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); |
| 2079 | p->size = nbits; | 2078 | p->size = nbits; |
| 2080 | 2079 | ||
| 2081 | /* Clear padding at the end. If NBITS != 0 this initializes more | 2080 | /* Clear padding at the end. */ |
| 2082 | than it needs to, but that's OK. */ | 2081 | if (words) |
| 2083 | p->data[words - 1] = 0; | 2082 | p->data[words - 1] = 0; |
| 2084 | 2083 | ||
| 2085 | return val; | 2084 | return val; |
| 2086 | } | 2085 | } |
diff --git a/src/data.c b/src/data.c index 33dd11049ec..bdd56bf0f62 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -3054,60 +3054,64 @@ bool_vector_binop_driver (Lisp_Object a, | |||
| 3054 | switch (op) | 3054 | switch (op) |
| 3055 | { | 3055 | { |
| 3056 | case bool_vector_exclusive_or: | 3056 | case bool_vector_exclusive_or: |
| 3057 | while (destdata[i] == (adata[i] ^ bdata[i])) | 3057 | for (; i < nr_words; i++) |
| 3058 | if (! (++i < nr_words)) | 3058 | if (destdata[i] != (adata[i] ^ bdata[i])) |
| 3059 | return Qnil; | 3059 | goto set_dest; |
| 3060 | break; | 3060 | break; |
| 3061 | 3061 | ||
| 3062 | case bool_vector_subsetp: | 3062 | case bool_vector_subsetp: |
| 3063 | case bool_vector_union: | 3063 | for (; i < nr_words; i++) |
| 3064 | while (destdata[i] == (adata[i] | bdata[i])) | 3064 | if (adata[i] &~ bdata[i]) |
| 3065 | if (! (++i < nr_words)) | ||
| 3066 | return Qnil; | 3065 | return Qnil; |
| 3066 | return Qt; | ||
| 3067 | |||
| 3068 | case bool_vector_union: | ||
| 3069 | for (; i < nr_words; i++) | ||
| 3070 | if (destdata[i] != (adata[i] | bdata[i])) | ||
| 3071 | goto set_dest; | ||
| 3067 | break; | 3072 | break; |
| 3068 | 3073 | ||
| 3069 | case bool_vector_intersection: | 3074 | case bool_vector_intersection: |
| 3070 | while (destdata[i] == (adata[i] & bdata[i])) | 3075 | for (; i < nr_words; i++) |
| 3071 | if (! (++i < nr_words)) | 3076 | if (destdata[i] != (adata[i] & bdata[i])) |
| 3072 | return Qnil; | 3077 | goto set_dest; |
| 3073 | break; | 3078 | break; |
| 3074 | 3079 | ||
| 3075 | case bool_vector_set_difference: | 3080 | case bool_vector_set_difference: |
| 3076 | while (destdata[i] == (adata[i] &~ bdata[i])) | 3081 | for (; i < nr_words; i++) |
| 3077 | if (! (++i < nr_words)) | 3082 | if (destdata[i] != (adata[i] &~ bdata[i])) |
| 3078 | return Qnil; | 3083 | goto set_dest; |
| 3079 | break; | 3084 | break; |
| 3080 | } | 3085 | } |
| 3086 | |||
| 3087 | return Qnil; | ||
| 3081 | } | 3088 | } |
| 3082 | 3089 | ||
| 3090 | set_dest: | ||
| 3083 | switch (op) | 3091 | switch (op) |
| 3084 | { | 3092 | { |
| 3085 | case bool_vector_exclusive_or: | 3093 | case bool_vector_exclusive_or: |
| 3086 | do | 3094 | for (; i < nr_words; i++) |
| 3087 | destdata[i] = adata[i] ^ bdata[i]; | 3095 | destdata[i] = adata[i] ^ bdata[i]; |
| 3088 | while (++i < nr_words); | ||
| 3089 | break; | ||
| 3090 | |||
| 3091 | case bool_vector_subsetp: | ||
| 3092 | break; | 3096 | break; |
| 3093 | 3097 | ||
| 3094 | case bool_vector_union: | 3098 | case bool_vector_union: |
| 3095 | do | 3099 | for (; i < nr_words; i++) |
| 3096 | destdata[i] = adata[i] | bdata[i]; | 3100 | destdata[i] = adata[i] | bdata[i]; |
| 3097 | while (++i < nr_words); | ||
| 3098 | break; | 3101 | break; |
| 3099 | 3102 | ||
| 3100 | case bool_vector_intersection: | 3103 | case bool_vector_intersection: |
| 3101 | do | 3104 | for (; i < nr_words; i++) |
| 3102 | destdata[i] = adata[i] & bdata[i]; | 3105 | destdata[i] = adata[i] & bdata[i]; |
| 3103 | while (++i < nr_words); | ||
| 3104 | break; | 3106 | break; |
| 3105 | 3107 | ||
| 3106 | case bool_vector_set_difference: | 3108 | case bool_vector_set_difference: |
| 3107 | do | 3109 | for (; i < nr_words; i++) |
| 3108 | destdata[i] = adata[i] &~ bdata[i]; | 3110 | destdata[i] = adata[i] &~ bdata[i]; |
| 3109 | while (++i < nr_words); | ||
| 3110 | break; | 3111 | break; |
| 3112 | |||
| 3113 | default: | ||
| 3114 | eassume (0); | ||
| 3111 | } | 3115 | } |
| 3112 | 3116 | ||
| 3113 | return dest; | 3117 | return dest; |
diff --git a/src/lisp.h b/src/lisp.h index 8521c87e5d7..a9aac2cc0bb 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -1213,7 +1213,7 @@ struct Lisp_Bool_Vector | |||
| 1213 | /* This is the size in bits. */ | 1213 | /* This is the size in bits. */ |
| 1214 | EMACS_INT size; | 1214 | EMACS_INT size; |
| 1215 | /* The actual bits, packed into bytes. | 1215 | /* The actual bits, packed into bytes. |
| 1216 | Zeros fill out the last word as needed; there's always at least one word. | 1216 | Zeros fill out the last word if needed. |
| 1217 | The bits are in little-endian order in the bytes, and | 1217 | The bits are in little-endian order in the bytes, and |
| 1218 | the bytes are in little-endian order in the words. */ | 1218 | the bytes are in little-endian order in the words. */ |
| 1219 | bits_word data[FLEXIBLE_ARRAY_MEMBER]; | 1219 | bits_word data[FLEXIBLE_ARRAY_MEMBER]; |