From eef20e02d25a16f71ad0904644d68450a6181fe2 Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Thu, 27 Jun 2019 16:19:25 +0000 Subject: [PATCH] Fix minor image bugs. * src/image.c (valid_image_p): Don't check value elements of the plist for key equality. (parse_image_spec): Use FOR_EACH_TAIL_SAFE to abort for circular structures. Fix off-by-one error. (image_spec_value): Handle circular structures. (equal_lists): Introduce; compares two lists' elements with `eq' (search_image_cache): Don't call Fequal from redisplay code. --- src/image.c | 73 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/src/image.c b/src/image.c index 7b648c46ae..89ba2b9d29 100644 --- a/src/image.c +++ b/src/image.c @@ -800,17 +800,22 @@ valid_image_p (Lisp_Object object) { Lisp_Object tail = XCDR (object); FOR_EACH_TAIL_SAFE (tail) - if (EQ (XCAR (tail), QCtype)) - { - tail = XCDR (tail); - if (CONSP (tail)) - { - struct image_type const *type = lookup_image_type (XCAR (tail)); - if (type) - return type->valid_p (object); - } - break; - } + { + if (EQ (XCAR (tail), QCtype)) + { + tail = XCDR (tail); + if (CONSP (tail)) + { + struct image_type const *type = lookup_image_type (XCAR (tail)); + if (type) + return type->valid_p (object); + } + break; + } + tail = XCDR (tail); + if (! CONSP (tail)) + return false; + } } return false; @@ -897,7 +902,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, return 0; plist = XCDR (spec); - while (CONSP (plist)) + FOR_EACH_TAIL_SAFE (plist) { Lisp_Object key, value; @@ -911,7 +916,6 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, if (!CONSP (plist)) return 0; value = XCAR (plist); - plist = XCDR (plist); /* Find key in KEYWORDS. Error if not found. */ for (i = 0; i < nkeywords; ++i) @@ -921,10 +925,10 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, if (i == nkeywords) continue; - /* Record that we recognized the keyword. If a keywords + /* Record that we recognized the keyword. If a keyword was found more than once, it's an error. */ keywords[i].value = value; - if (keywords[i].count > 1) + if (keywords[i].count > 0) return 0; ++keywords[i].count; @@ -1006,14 +1010,22 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, if (EQ (key, QCtype) && !EQ (type, value)) return 0; - } - /* Check that all mandatory fields are present. */ - for (i = 0; i < nkeywords; ++i) - if (keywords[i].mandatory_p && keywords[i].count == 0) - return 0; + if (EQ (XCDR (plist), Qnil)) + { + /* Check that all mandatory fields are present. */ + for (i = 0; i < nkeywords; ++i) + if (keywords[i].mandatory_p && keywords[i].count == 0) + return 0; + + return 1; + } + + if (! CONSP (plist)) + return 0; + } - return NILP (plist); + return 0; } @@ -1028,9 +1040,8 @@ image_spec_value (Lisp_Object spec, Lisp_Object key, bool *found) eassert (valid_image_p (spec)); - for (tail = XCDR (spec); - CONSP (tail) && CONSP (XCDR (tail)); - tail = XCDR (XCDR (tail))) + tail = XCDR (spec); + FOR_EACH_TAIL_SAFE (tail) { if (EQ (XCAR (tail), key)) { @@ -1038,6 +1049,9 @@ image_spec_value (Lisp_Object spec, Lisp_Object key, bool *found) *found = 1; return XCAR (XCDR (tail)); } + tail = XCDR (tail); + if (! CONSP (tail)) + break; } if (found) @@ -1572,6 +1586,15 @@ make_image_cache (void) return c; } +/* Compare two (non-circular) lists, comparing each element with `eq'. */ +static bool +equal_lists (Lisp_Object a, Lisp_Object b) +{ + while (CONSP (a) && CONSP (b) && Feq (XCAR (a), XCAR (b))) + a = XCDR (a), b = XCDR (b); + + return EQ (a, b); +} /* Find an image matching SPEC in the cache, and return it. If no image is found, return NULL. */ @@ -1598,7 +1621,7 @@ search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash) for (img = c->buckets[i]; img; img = img->next) if (img->hash == hash - && !NILP (Fequal (img->spec, spec)) + && !equal_lists (img->spec, spec) && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f) && img->frame_background == FRAME_BACKGROUND_PIXEL (f)) break; -- 2.20.1