commit 593c367b0727affc739832ab4f4bdb9d7dd1ddd7 (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Fri May 18 15:53:21 2018 -0700 * src/alloc.c: Fix comment. diff --git a/src/alloc.c b/src/alloc.c index 231ade5cf8..d959c55350 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -508,8 +508,8 @@ pointer_align (void *ptr, int alignment) DEFINE_KEY_OPS_AS_MACROS, for performance in that case. The macro_* macros are private to this section of code. */ -/* Add a pointer an an integer without complaint about a pointer going - out of range of the underlying array. */ +/* Add a pointer P to an integer I without gcc -fsanitize complaining + about the result being out of range of the underlying array. */ #define macro_PNTR_ADD(p, i) ((p) + (i)) commit a1c925fd41818cb8ad209762739b220efb919d1e Author: Paul Eggert Date: Fri May 18 15:45:42 2018 -0700 Port to GCC 8 -fsanitize=undefined In GCC 8, gcc -fsanitize=undefined flags the undefined behavior that Emacs relies on in its XPNTR and XSYMBOL low-level functions. Disable undefined sanitization in these functions. Although this disabling doesn’t suffice if DEFINE_KEY_OPS_AS_MACROS is true, it works for -fsanitize=undefined -DINLINING=0, which is good enough. * src/alloc.c (macro_PNTR_ADD): New macro. (PNTR_ADD): New function and macro. The function disables -fsanitize=undefined. (macro_XPNTR): Use it. * src/conf_post.h (ATTRIBUTE_NO_SANITIZE_UNDEFINED): New macro. * src/lisp.h (XSYMBOL): Disable -fsanitize=undefined. diff --git a/src/alloc.c b/src/alloc.c index 8264e0623c..231ade5cf8 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -503,18 +503,34 @@ pointer_align (void *ptr, int alignment) return (void *) ROUNDUP ((uintptr_t) ptr, alignment); } -/* Extract the pointer hidden within O. Define this as a function, as - functions are cleaner and can be used in debuggers. Also, define - it as a macro if being compiled with GCC without optimization, for - performance in that case. macro_XPNTR is private to this section - of code. */ +/* Define PNTR_ADD and XPNTR as functions, which are cleaner and can + be used in debuggers. Also, define them as macros if + DEFINE_KEY_OPS_AS_MACROS, for performance in that case. + The macro_* macros are private to this section of code. */ + +/* Add a pointer an an integer without complaint about a pointer going + out of range of the underlying array. */ + +#define macro_PNTR_ADD(p, i) ((p) + (i)) + +static char * ATTRIBUTE_NO_SANITIZE_UNDEFINED ATTRIBUTE_UNUSED +PNTR_ADD (char *p, EMACS_UINT i) +{ + return macro_PNTR_ADD (p, i); +} + +#if DEFINE_KEY_OPS_AS_MACROS +# define PNTR_ADD(p, i) macro_PNTR_ADD (p, i) +#endif + +/* Extract the pointer hidden within O. */ #define macro_XPNTR(o) \ ((void *) \ (SYMBOLP (o) \ - ? ((char *) lispsym \ - - ((EMACS_UINT) Lisp_Symbol << (USE_LSB_TAG ? 0 : VALBITS)) \ - + XLI (o)) \ + ? PNTR_ADD ((char *) lispsym, \ + (XLI (o) \ + - ((EMACS_UINT) Lisp_Symbol << (USE_LSB_TAG ? 0 : VALBITS)))) \ : (char *) XLP (o) - (XLI (o) & ~VALMASK))) static ATTRIBUTE_UNUSED void * diff --git a/src/conf_post.h b/src/conf_post.h index 00e283d289..bf2cfc4f05 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -67,6 +67,7 @@ typedef bool bool_bf; # define __has_attribute_externally_visible GNUC_PREREQ (4, 1, 0) # define __has_attribute_no_address_safety_analysis false # define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0) +# define __has_attribute_no_sanitize_undefined GNUC_PREREQ (4, 9, 0) #endif /* Simulate __has_builtin on compilers that lack it. It is used only @@ -338,6 +339,17 @@ extern int emacs_setenv_TZ (char const *); # define ATTRIBUTE_NO_SANITIZE_ADDRESS #endif +/* Attribute of functions whose undefined behavior should not be sanitized. */ + +#if __has_attribute (no_sanitize_undefined) +# define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__ ((no_sanitize_undefined)) +#elif __has_attribute (no_sanitize) +# define ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__ ((no_sanitize ("undefined"))) +#else +# define ATTRIBUTE_NO_SANITIZE_UNDEFINED +#endif + /* gcc -fsanitize=address does not work with vfork in Fedora 25 x86-64. For now, assume that this problem occurs on all platforms. */ #if ADDRESS_SANITIZER && !defined vfork diff --git a/src/lisp.h b/src/lisp.h index a18b64a588..ee2e72d32b 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -900,7 +900,7 @@ INLINE bool return lisp_h_SYMBOLP (x); } -INLINE struct Lisp_Symbol * +INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED (XSYMBOL) (Lisp_Object a) { #if USE_LSB_TAG commit f4d9fd3dd45f767eca33fbf1beee40da790fa74e Author: Lars Ingebrigtsen Date: Fri May 18 16:05:02 2018 +0200 (gnus-blocked-images): Clarify privacy implications * lisp/gnus/gnus-art.el (gnus-blocked-images): Clarify the privacy implication of altering the value of this variable. diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 869ff4e661..f6120dc5c7 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -1616,6 +1616,16 @@ It is a string, such as \"PGP\". If nil, ask user." (defcustom gnus-blocked-images 'gnus-block-private-groups "Images that have URLs matching this regexp will be blocked. +Note that the main reason external images are included in HTML +emails (these days) is to allow tracking whether you've read the +email message or not. If you allow loading images in HTML +emails, you give up privacy. + +The default value of this variable blocks loading external +resources when reading email groups (and therefore stops +tracking), but allows loading external resources when reading +from NNTP newsgroups and the like. + This can also be a function to be evaluated. If so, it will be called with the group name as the parameter, and should return a regexp." commit 3aab8626ba5080bb04d0fdae52d99c850a842a52 Author: Eli Zaretskii Date: Fri May 18 16:34:19 2018 +0300 Fix decoding of directories when "~" includes non-ASCII chars * src/fileio.c (Fexpand_file_name): Don't build multibyte strings from unibyte non-ASCII strings when NAME and DEFAULT_DIRECTORY have different multibyteness, as this adds bytes to the byte sequence, and in some situations, e.g., when the home directory includes non-ASCII characters, can fail file APIs. (Bug#30755) * lisp/startup.el (normal-top-level): Make sure default-directory is set to a multibyte string when decoded on MS-Windows. diff --git a/lisp/startup.el b/lisp/startup.el index 5b2d3e58cb..83fd190ea2 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -560,9 +560,17 @@ It is the default value of the variable `top-level'." (if default-directory (setq default-directory (if (eq system-type 'windows-nt) - ;; Convert backslashes to forward slashes. - (expand-file-name - (decode-coding-string default-directory coding t)) + ;; We pass the decoded default-directory as + ;; the 2nd arg to expand-file-name to make + ;; sure it sees a multibyte string as the + ;; default directory; this avoids the side + ;; effect of returning a unibyte string from + ;; expand-file-name because it still sees + ;; the undecoded value of default-directory. + (let ((defdir (decode-coding-string default-directory + coding t))) + ;; Convert backslashes to forward slashes. + (expand-file-name defdir defdir)) (decode-coding-string default-directory coding t)))))) ;; Decode all the important variables and directory lists, now diff --git a/src/fileio.c b/src/fileio.c index 2f8358f01b..e8d966e163 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -867,33 +867,78 @@ the root directory. */) } } multibyte = STRING_MULTIBYTE (name); - if (multibyte != STRING_MULTIBYTE (default_directory)) + bool defdir_multibyte = STRING_MULTIBYTE (default_directory); + if (multibyte != defdir_multibyte) { + /* We want to make both NAME and DEFAULT_DIRECTORY have the same + multibyteness. Strategy: + . If either NAME or DEFAULT_DIRECTORY is pure-ASCII, they + can be converted to the multibyteness of the other one + while keeping the same byte sequence. + . If both are non-ASCII, the only safe conversion is to + convert the multibyte one to be unibyte, because the + reverse conversion potentially adds bytes while raw bytes + are converted to their multibyte forms, which we will be + unable to account for, since the information about the + original multibyteness is lost. If those additional bytes + later leak to system APIs because they are not encoded or + because they are converted to unibyte strings by keeping + the data, file APIs will fail. + + Note: One could argue that if we see a multibyte string, it + is evidence that file-name decoding was already set up, and + we could convert unibyte strings to multibyte using + DECODE_FILE. However, this is risky, because the likes of + string_to_multibyte are able of creating multibyte strings + without any decoding. */ if (multibyte) { - unsigned char *p = SDATA (name); + bool name_ascii_p = SCHARS (name) == SBYTES (name); + unsigned char *p = SDATA (default_directory); - while (*p && ASCII_CHAR_P (*p)) - p++; - if (*p == '\0') + if (!name_ascii_p) + while (*p && ASCII_CHAR_P (*p)) + p++; + if (name_ascii_p || *p != '\0') { - /* NAME is a pure ASCII string, and DEFAULT_DIRECTORY is - unibyte. Do not convert DEFAULT_DIRECTORY to - multibyte; instead, convert NAME to a unibyte string, - so that the result of this function is also a unibyte - string. This is needed during bootstrapping and - dumping, when Emacs cannot decode file names, because - the locale environment is not set up. */ + /* DEFAULT_DIRECTORY is unibyte and possibly non-ASCII. + Make a unibyte string out of NAME, and arrange for + the result of this function to be a unibyte string. + This is needed during bootstrapping and dumping, when + Emacs cannot decode file names, because the locale + environment is not set up. */ name = make_unibyte_string (SSDATA (name), SBYTES (name)); multibyte = 0; } else - default_directory = string_to_multibyte (default_directory); + { + /* NAME is non-ASCII and multibyte, and + DEFAULT_DIRECTORY is unibyte and pure-ASCII: make a + multibyte string out of DEFAULT_DIRECTORY's data. */ + default_directory = + make_multibyte_string (SSDATA (default_directory), + SCHARS (default_directory), + SCHARS (default_directory)); + } } else { - name = string_to_multibyte (name); - multibyte = 1; + unsigned char *p = SDATA (name); + + while (*p && ASCII_CHAR_P (*p)) + p++; + if (*p == '\0') + { + /* DEFAULT_DIRECTORY is multibyte and NAME is unibyte + and pure-ASCII. Make a multibyte string out of + NAME's data. */ + name = make_multibyte_string (SSDATA (name), + SCHARS (name), SCHARS (name)); + multibyte = 1; + } + else + default_directory = make_unibyte_string (SSDATA (default_directory), + SBYTES (default_directory)); } }