commit d23a486ba27405acfda67a4dc387ade5e399a29b (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Sun May 14 18:44:36 2017 -0700 Fix address violation found by AddressSanitizer * src/process.c (connect_network_socket): Use struct sockaddr_storage, not struct sockaddr_in, to store info about a socket address. Problem reported by Philipp Stephani in: http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00314.html This fix is based on a patch by Philipp in: http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00357.html diff --git a/src/process.c b/src/process.c index 0edd092ef6..4a286391f8 100644 --- a/src/process.c +++ b/src/process.c @@ -3420,16 +3420,32 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, #ifdef HAVE_GETSOCKNAME if (p->port == 0) { - struct sockaddr_in sa1; + struct sockaddr_storage sa1; socklen_t len1 = sizeof (sa1); if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) { - Lisp_Object service; - service = make_number (ntohs (sa1.sin_port)); - contact = Fplist_put (contact, QCservice, service); /* Save the port number so that we can stash it in the process object later. */ - ((struct sockaddr_in *)sa)->sin_port = sa1.sin_port; + int port = -1; + switch (family) + { + case AF_INET: + ((struct sockaddr_in *) sa)->sin_port + = port = ((struct sockaddr_in *) &sa1)->sin_port; + break; +# ifdef AF_INET6 + case AF_INET6: + ((struct sockaddr_in6 *) sa)->sin6_port + = port = ((struct sockaddr_in6 *) &sa1)->sin6_port; + break; +# endif + } + + if (0 <= port) + { + Lisp_Object service = make_number (ntohs (port)); + contact = Fplist_put (contact, QCservice, service); + } } } #endif @@ -3535,7 +3551,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, #ifdef HAVE_GETSOCKNAME if (!p->is_server) { - struct sockaddr_in sa1; + struct sockaddr_storage sa1; socklen_t len1 = sizeof (sa1); if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) contact = Fplist_put (contact, QClocal, commit e6f64df9c2b443d3385c2c25c29ccd5283d37e3f Author: Gemini Lasswell Date: Sat May 13 11:35:49 2017 -0700 Make edebug-step-in work on generic methods (Bug#22294) * lisp/emacs-lisp/edebug.el (edebug-match-cl-generic-method-args): New function to implement the edebug-form-spec property of the symbol cl-generic-method-args. (edebug-instrument-function): If the function is a generic function, find and instrument all of its methods. Return a list instead of a single symbol. (edebug-instrument-callee): Now returns a list. Update docstring. (edebug-step-in): Handle the list returned by edebug-instrument-callee. * lisp/emacs-lisp/cl-generic.el (cl-defmethod): Use name and cl-generic-method-args in its Edebug spec. * lisp/emacs-lisp/eieio-compat.el (defmethod): Use name and cl-generic-method-args in its Edebug spec. * lisp/subr.el (method-files): New function. * test/lisp/subr-tests.el (subr-tests--method-files--finds-methods) (subr-tests--method-files--nonexistent-methods): New tests. diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 068f4fb0c8..c64376b940 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -413,12 +413,12 @@ The set of acceptable TYPEs (also called \"specializers\") is defined (declare (doc-string 3) (indent 2) (debug (&define ; this means we are defining something - [&or symbolp ("setf" symbolp)] + [&or name ("setf" name :name setf)] ;; ^^ This is the methods symbol [ &rest atom ] ; Multiple qualifiers are allowed. ; Like in CLOS spec, we support ; any non-list values. - listp ; arguments + cl-generic-method-args ; arguments [ &optional stringp ] ; documentation string def-body))) ; part to be debugged (let ((qualifiers nil)) diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 4116e31d0a..65e30f8677 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -1607,6 +1607,7 @@ expressions; a `progn' form will be returned enclosing these forms." ;; Less frequently used: ;; (function . edebug-match-function) (lambda-expr . edebug-match-lambda-expr) + (cl-generic-method-args . edebug-match-cl-generic-method-args) (¬ . edebug-match-¬) (&key . edebug-match-&key) (place . edebug-match-place) @@ -1900,6 +1901,16 @@ expressions; a `progn' form will be returned enclosing these forms." spec)) nil) +(defun edebug-match-cl-generic-method-args (cursor) + (let ((args (edebug-top-element-required cursor "Expected arguments"))) + (if (not (consp args)) + (edebug-no-match cursor "List expected")) + ;; Append the arguments to edebug-def-name. + (setq edebug-def-name + (intern (format "%s %s" edebug-def-name args))) + (edebug-move-cursor cursor) + (list args))) + (defun edebug-match-arg (cursor) ;; set the def-args bound in edebug-defining-form (let ((edebug-arg (edebug-top-element-required cursor "Expected arg"))) @@ -3186,8 +3197,11 @@ go to the end of the last sexp, or if that is the same point, then step." ))))) (defun edebug-instrument-function (func) - ;; Func should be a function symbol. - ;; Return the function symbol, or nil if not instrumented. + "Instrument the function or generic method FUNC. +Return the list of function symbols which were instrumented. +This may be simply (FUNC) for a normal function, or a list of +generated symbols for methods. If a function or method to +instrument cannot be found, signal an error." (let ((func-marker (get func 'edebug))) (cond ((and (markerp func-marker) (marker-buffer func-marker)) @@ -3195,10 +3209,24 @@ go to the end of the last sexp, or if that is the same point, then step." (with-current-buffer (marker-buffer func-marker) (goto-char func-marker) (edebug-eval-top-level-form) - func)) + (list func))) ((consp func-marker) (message "%s is already instrumented." func) - func) + (list func)) + ((get func 'cl--generic) + (let ((method-defs (method-files func)) + symbols) + (unless method-defs + (error "Could not find any method definitions for %s" func)) + (pcase-dolist (`(,file . ,spec) method-defs) + (let* ((loc (find-function-search-for-symbol spec 'cl-defmethod file))) + (unless (cdr loc) + (error "Could not find the definition for %s in its file" spec)) + (with-current-buffer (car loc) + (goto-char (cdr loc)) + (edebug-eval-top-level-form) + (push (edebug-form-data-symbol) symbols)))) + symbols)) (t (let ((loc (find-function-noselect func t))) (unless (cdr loc) @@ -3206,13 +3234,16 @@ go to the end of the last sexp, or if that is the same point, then step." (with-current-buffer (car loc) (goto-char (cdr loc)) (edebug-eval-top-level-form) - func)))))) + (list func))))))) (defun edebug-instrument-callee () "Instrument the definition of the function or macro about to be called. Do this when stopped before the form or it will be too late. One side effect of using this command is that the next time the -function or macro is called, Edebug will be called there as well." +function or macro is called, Edebug will be called there as well. +If the callee is a generic function, Edebug will instrument all +the methods, not just the one which is about to be called. Return +the list of symbols which were instrumented." (interactive) (if (not (looking-at "(")) (error "You must be before a list form") @@ -3227,15 +3258,15 @@ function or macro is called, Edebug will be called there as well." (defun edebug-step-in () - "Step into the definition of the function or macro about to be called. + "Step into the definition of the function, macro or method about to be called. This first does `edebug-instrument-callee' to ensure that it is instrumented. Then it does `edebug-on-entry' and switches to `go' mode." (interactive) - (let ((func (edebug-instrument-callee))) - (if func + (let ((funcs (edebug-instrument-callee))) + (if funcs (progn - (edebug-on-entry func 'temp) - (edebug-go-mode nil))))) + (mapc (lambda (func) (edebug-on-entry func 'temp)) funcs) + (edebug-go-mode nil))))) (defun edebug-on-entry (function &optional flag) "Cause Edebug to stop when FUNCTION is called. diff --git a/lisp/emacs-lisp/eieio-compat.el b/lisp/emacs-lisp/eieio-compat.el index fe65ae0262..e6e6d11870 100644 --- a/lisp/emacs-lisp/eieio-compat.el +++ b/lisp/emacs-lisp/eieio-compat.el @@ -105,10 +105,10 @@ Summary: (declare (doc-string 3) (obsolete cl-defmethod "25.1") (debug (&define ; this means we are defining something - [&or symbolp ("setf" symbolp)] + [&or name ("setf" name :name setf)] ;; ^^ This is the methods symbol [ &optional symbolp ] ; this is key :before etc - listp ; arguments + cl-generic-method-args ; arguments [ &optional stringp ] ; documentation string def-body ; part to be debugged ))) diff --git a/lisp/subr.el b/lisp/subr.el index 02e7993223..8d5d2a779c 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -2026,6 +2026,25 @@ definition, variable definition, or face definition only." (setq files (cdr files))) file))) +(defun method-files (method) + "Return a list of files where METHOD is defined by `cl-defmethod'. +The list will have entries of the form (FILE . (METHOD ...)) +where (METHOD ...) contains the qualifiers and specializers of +the method and is a suitable argument for +`find-function-search-for-symbol'. Filenames are absolute." + (let ((files load-history) + result) + (while files + (let ((defs (cdr (car files)))) + (while defs + (let ((def (car defs))) + (if (and (eq (car-safe def) 'cl-defmethod) + (eq (cadr def) method)) + (push (cons (car (car files)) (cdr def)) result))) + (setq defs (cdr defs)))) + (setq files (cdr files))) + result)) + (defun locate-library (library &optional nosuffix path interactive-call) "Show the precise file name of Emacs library LIBRARY. LIBRARY should be a relative file name of the library, a string. diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 0d243cc5d8..8fa258d12e 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -291,5 +291,29 @@ cf. Bug#25477." (should-error (eval '(dolist "foo") t) :type 'wrong-type-argument)) +(require 'cl-generic) +(cl-defgeneric subr-tests--generic (x)) +(cl-defmethod subr-tests--generic ((x string)) + (message "%s is a string" x)) +(cl-defmethod subr-tests--generic ((x integer)) + (message "%s is a number" x)) +(cl-defgeneric subr-tests--generic-without-methods (x y)) +(defvar subr-tests--this-file (or load-file-name buffer-file-name)) + +(ert-deftest subr-tests--method-files--finds-methods () + "`method-files' returns a list of files and methods for a generic function." + (let ((retval (method-files 'subr-tests--generic))) + (should (equal (length retval) 2)) + (mapc (lambda (x) + (should (equal (car x) subr-tests--this-file)) + (should (equal (cadr x) 'subr-tests--generic))) + retval) + (should-not (equal (nth 0 retval) (nth 1 retval))))) + +(ert-deftest subr-tests--method-files--nonexistent-methods () + "`method-files' returns nil if asked to find a method which doesn't exist." + (should-not (method-files 'subr-tests--undefined-generic)) + (should-not (method-files 'subr-tests--generic-without-methods))) + (provide 'subr-tests) ;;; subr-tests.el ends here commit 10037e4be2358597125a05db93f6fee551131d83 Author: Paul Eggert Date: Sun May 14 12:39:26 2017 -0700 Merge from gnulib This incorporates: 2017-05-14 same-inode: Adapt for windows-stat-inodes 2017-05-14 windows-stat-inodes: New module 2017-05-14 stat-time: Adapt for windows-stat-timespec * lib/gnulib.mk.in: Regenerate. * lib/stat-time.h, lib/sys_types.in.h, m4/sys_types_h.m4: Copy from gnulib. diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index d4afafbecc..6d85dc5958 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -838,6 +838,7 @@ WERROR_CFLAGS = @WERROR_CFLAGS@ WIDGET_OBJ = @WIDGET_OBJ@ WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINDOWS_STAT_INODES = @WINDOWS_STAT_INODES@ WINDOWS_STAT_TIMESPEC = @WINDOWS_STAT_TIMESPEC@ WINDOW_SYSTEM_OBJ = @WINDOW_SYSTEM_OBJ@ WINDRES = @WINDRES@ @@ -2693,6 +2694,7 @@ sys/types.h: sys_types.in.h $(top_builddir)/config.status -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's|@''WINDOWS_STAT_INODES''@|$(WINDOWS_STAT_INODES)|g' \ < $(srcdir)/sys_types.in.h; \ } > $@-t && \ mv $@-t $@ diff --git a/lib/stat-time.h b/lib/stat-time.h index 88dcc7f3e0..9e45e85565 100644 --- a/lib/stat-time.h +++ b/lib/stat-time.h @@ -170,8 +170,12 @@ get_stat_birthtime (struct stat const *st) /* Native Windows platforms (but not Cygwin) put the "file creation time" in st_ctime (!). See . */ +# if _GL_WINDOWS_STAT_TIMESPEC + t = st->st_ctim; +# else t.tv_sec = st->st_ctime; t.tv_nsec = 0; +# endif #else /* Birth time is not supported. */ t.tv_sec = -1; diff --git a/lib/sys_types.in.h b/lib/sys_types.in.h index 30ebfbdd29..3cea44884e 100644 --- a/lib/sys_types.in.h +++ b/lib/sys_types.in.h @@ -42,6 +42,48 @@ # define _GL_WINDOWS_64_BIT_OFF_T 1 #endif +/* Override dev_t and ino_t if distinguishable inodes support is requested + on native Windows. */ +#if @WINDOWS_STAT_INODES@ + +# if @WINDOWS_STAT_INODES@ == 2 +/* Experimental, not useful in Windows 10. */ + +/* Define dev_t to a 64-bit type. */ +# if !defined GNULIB_defined_dev_t +typedef unsigned long long int rpl_dev_t; +# undef dev_t +# define dev_t rpl_dev_t +# define GNULIB_defined_dev_t 1 +# endif + +/* Define ino_t to a 128-bit type. */ +# if !defined GNULIB_defined_ino_t +/* MSVC does not have a 128-bit integer type. + GCC has a 128-bit integer type __int128, but only on 64-bit targets. */ +typedef struct { unsigned long long int _gl_ino[2]; } rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# else /* @WINDOWS_STAT_INODES@ == 1 */ + +/* Define ino_t to a 64-bit type. */ +# if !defined GNULIB_defined_ino_t +typedef unsigned long long int rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# endif + +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_STAT_INODES @WINDOWS_STAT_INODES@ + +#endif + /* MSVC 9 defines size_t in , not in . */ /* But avoid namespace pollution on glibc systems. */ #if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \ diff --git a/m4/sys_types_h.m4 b/m4/sys_types_h.m4 index 2eb4e9e44e..e5906709f6 100644 --- a/m4/sys_types_h.m4 +++ b/m4/sys_types_h.m4 @@ -1,4 +1,4 @@ -# sys_types_h.m4 serial 6 +# sys_types_h.m4 serial 7 dnl Copyright (C) 2011-2017 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -17,6 +17,14 @@ AC_DEFUN_ONCE([gl_SYS_TYPES_H], dnl Whether to override the 'off_t' type. AC_REQUIRE([gl_TYPE_OFF_T]) + + dnl Whether to override the 'dev_t' and 'ino_t' types. + m4_ifdef([gl_WINDOWS_STAT_INODES], [ + AC_REQUIRE([gl_WINDOWS_STAT_INODES]) + ], [ + WINDOWS_STAT_INODES=0 + ]) + AC_SUBST([WINDOWS_STAT_INODES]) ]) AC_DEFUN([gl_SYS_TYPES_H_DEFAULTS], commit 792ffa022380e05d49437e47823cfdf82337a253 Author: Eli Zaretskii Date: Sun May 14 19:02:50 2017 +0300 Remove gettimeofday from w32 sources * lib-src/ntlib.c (gettimeofday): * nt/inc/sys/time.h (gettimeofday, struct timezone): Remove unused function 'gettimeofday' and all of its supporting code. diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c index 4bffc612f9..78ba9061f6 100644 --- a/lib-src/ntlib.c +++ b/lib-src/ntlib.c @@ -50,8 +50,6 @@ struct timezone }; #endif -void gettimeofday (struct timeval *, struct timezone *); - #define MAXPATHLEN _MAX_PATH /* Emulate sleep...we could have done this with a define, but that @@ -229,29 +227,6 @@ getpass (const char * prompt) return NULL; } -/* This is needed because lib/gettime.c calls gettimeofday, which MSVC - doesn't have. Copied from w32.c. */ -void -gettimeofday (struct timeval *tv, struct timezone *tz) -{ - struct _timeb tb; - _ftime (&tb); - - tv->tv_sec = tb.time; - tv->tv_usec = tb.millitm * 1000L; - /* Implementation note: _ftime sometimes doesn't update the dstflag - according to the new timezone when the system timezone is - changed. We could fix that by using GetSystemTime and - GetTimeZoneInformation, but that doesn't seem necessary, since - Emacs always calls gettimeofday with the 2nd argument NULL (see - current_emacs_time). */ - if (tz) - { - tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */ - tz->tz_dsttime = tb.dstflag; /* type of dst correction */ - } -} - int fchown (int fd, unsigned uid, unsigned gid) { diff --git a/nt/inc/sys/time.h b/nt/inc/sys/time.h index 88ea32bc80..de06c116ce 100644 --- a/nt/inc/sys/time.h +++ b/nt/inc/sys/time.h @@ -25,25 +25,6 @@ struct timeval #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 #endif /* _TIMEVAL_DEFINED */ -#ifndef _TIMEZONE_DEFINED -#define _TIMEZONE_DEFINED -struct timezone -{ - int tz_minuteswest; /* minutes west of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; -#endif - - -/* This needs to be compatible with Posix signature, in order to pass - the configure test for the type of the second argument; see - m4/gettimeofday.m4. We use '__restrict' here, rather than - 'restrict', for the benefit of the old nt/configure.bat build, - which does not force the use of -std= switch to GCC, and that - causes compilation errors with 'restrict', which is a C99 - extension. */ -int gettimeofday (struct timeval *__restrict, void *__restrict); - #define ITIMER_REAL 0 #define ITIMER_PROF 1 diff --git a/src/w32.c b/src/w32.c index 878b22473a..fa3cbe183f 100644 --- a/src/w32.c +++ b/src/w32.c @@ -2978,33 +2978,6 @@ emacs_root_dir (void) return root_dir; } -#include - -/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */ -int -gettimeofday (struct timeval *__restrict tv, void *__restrict tzv) -{ - struct _timeb tb; - _ftime (&tb); - - tv->tv_sec = tb.time; - tv->tv_usec = tb.millitm * 1000L; - /* Implementation note: _ftime sometimes doesn't update the dstflag - according to the new timezone when the system timezone is - changed. We could fix that by using GetSystemTime and - GetTimeZoneInformation, but that doesn't seem necessary, since - Emacs always calls gettimeofday with the 2nd argument NULL (see - current_emacs_time). */ - if (tzv) - { - struct timezone *tz = (struct timezone *)tzv; - - tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */ - tz->tz_dsttime = tb.dstflag; /* type of dst correction */ - } - return 0; -} - /* Emulate fdutimens. */ /* Set the access and modification time stamps of FD (a.k.a. FILE) to be commit 3af6909f3249dc8d74349f000117f7063f71adff Author: Eli Zaretskii Date: Sun May 14 17:53:39 2017 +0300 Fix the MS-Windows build * nt/inc/sys/time.h (gettimeofday): * src/w32.c (gettimeofday): Adjust signature to match Gnulib. diff --git a/nt/inc/sys/time.h b/nt/inc/sys/time.h index f8fb022d22..88ea32bc80 100644 --- a/nt/inc/sys/time.h +++ b/nt/inc/sys/time.h @@ -42,7 +42,7 @@ struct timezone which does not force the use of -std= switch to GCC, and that causes compilation errors with 'restrict', which is a C99 extension. */ -int gettimeofday (struct timeval *__restrict, struct timezone *__restrict); +int gettimeofday (struct timeval *__restrict, void *__restrict); #define ITIMER_REAL 0 #define ITIMER_PROF 1 diff --git a/src/w32.c b/src/w32.c index f35ad67d82..878b22473a 100644 --- a/src/w32.c +++ b/src/w32.c @@ -2982,7 +2982,7 @@ emacs_root_dir (void) /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */ int -gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz) +gettimeofday (struct timeval *__restrict tv, void *__restrict tzv) { struct _timeb tb; _ftime (&tb); @@ -2995,8 +2995,10 @@ gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz) GetTimeZoneInformation, but that doesn't seem necessary, since Emacs always calls gettimeofday with the 2nd argument NULL (see current_emacs_time). */ - if (tz) + if (tzv) { + struct timezone *tz = (struct timezone *)tzv; + tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */ tz->tz_dsttime = tb.dstflag; /* type of dst correction */ }