1 new commit in XEmacs:
https://bitbucket.org/xemacs/xemacs/commits/046a3f85a39d/
Changeset: 046a3f85a39d
User: kehoea
Date: 2018-04-21 15:49:20+00:00
Summary: Better range checking, decoding Lisp values, for underlying C integer types
src/ChangeLog addition:
2018-04-21 Aidan Kehoe <kehoea(a)parhasard.net>
* data.c:
Provide macros to generalise the two-way conversion
between C integer types and Lisp values (fixnums, bignums, conses
of fixnums and, because GNU, floats).
Use these macros to generate conversion functions for OFF_T and
for uid_t. There may be scope down the line for further types, it
needs looking into.
* dired.c (Ffile_attributes):
Use OFF_T_to_lisp here.
* editfns.c:
* editfns.c (Ftemp_directory):
* editfns.c (Fuser_login_name):
* editfns.c (Fuser_uid):
* editfns.c (Fuser_real_uid):
Use lisp_to_uid_t, uid_t_to_lisp as appropriate in these
functions.
* fileio.c:
Remove the old lisp_to_off_t(). Use the new lisp_to_OFF_T.
* number.h:
Declare the new generated conversion functions for OFF_T and for
uid_t.
tests/ChangeLog addition:
2018-04-21 Aidan Kehoe <kehoea(a)parhasard.net>
* automated/os-tests.el (two-to-the-thirty-second):
Check that (user-login-name 4294967296) no longer gives "root", as
it used to do on 64-bit builds.
Affected #: 8 files
diff -r 368318a5c386 -r 046a3f85a39d src/ChangeLog
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,27 @@
+2018-04-21 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * data.c:
+ Provide macros to generalise the two-way conversion
+ between C integer types and Lisp values (fixnums, bignums, conses
+ of fixnums and, because GNU, floats).
+ Use these macros to generate conversion functions for OFF_T and
+ for uid_t. There may be scope down the line for further types, it
+ needs looking into.
+ * dired.c (Ffile_attributes):
+ Use OFF_T_to_lisp here.
+ * editfns.c:
+ * editfns.c (Ftemp_directory):
+ * editfns.c (Fuser_login_name):
+ * editfns.c (Fuser_uid):
+ * editfns.c (Fuser_real_uid):
+ Use lisp_to_uid_t, uid_t_to_lisp as appropriate in these
+ functions.
+ * fileio.c:
+ Remove the old lisp_to_off_t(). Use the new lisp_to_OFF_T.
+ * number.h:
+ Declare the new generated conversion functions for OFF_T and for
+ uid_t.
+
2018-04-21 Aidan Kehoe <kehoea(a)parhasard.net>
* lisp.h (NUMBER_FITS_IN_A_FIXNUM, NUMBER_FITS_IN_A_FIXNUM):
diff -r 368318a5c386 -r 046a3f85a39d src/data.c
--- a/src/data.c
+++ b/src/data.c
@@ -4099,6 +4099,217 @@
return EPHEMERONP (object) ? Qt : Qnil;
}
+/****************** Converting to and from specific C types ******************/
+
+#ifdef HAVE_BIGNUM
+#define LISP_INTEGER_TO_C_TYPE(c_type, objekt) \
+ if (INTEGERP (objekt)) \
+ do \
+ { \
+ check_integer_range (objekt, make_integer (min_lisp_to_c_type), \
+ make_integer (max_lisp_to_c_type)); \
+ if (FIXNUMP (objekt)) \
+ { \
+ return (c_type) XREALFIXNUM (objekt); \
+ } \
+ else if (BIGNUMP (objekt)) \
+ { \
+ if (sizeof (c_type) >= SIZEOF_EMACS_INT && \
+ bignum_fits_emacs_int_p (XBIGNUM_DATA (objekt))) \
+ { \
+ return (c_type) bignum_to_emacs_int (XBIGNUM_DATA \
+ (objekt)); \
+ } \
+ \
+ if (sizeof (c_type) >= sizeof (long long) && \
+ bignum_fits_llong_p (XBIGNUM_DATA (objekt))) \
+ { \
+ return (c_type) bignum_to_llong (XBIGNUM_DATA (objekt)); \
+ } \
+ \
+ if (sizeof (c_type) >= sizeof (long long) && \
+ bignum_fits_ullong_p (XBIGNUM_DATA (objekt))) \
+ { \
+ return (c_type) bignum_to_ullong (XBIGNUM_DATA (objekt)); \
+ } \
+ \
+ signal_error (Qunimplemented, \
+ "cannot decode this " #c_type, \
+ objekt); \
+ RETURN_NOT_REACHED ((c_type) -1); \
+ } \
+ } while (0)
+#define C_TYPE_TO_LISP_INTEGER(c_type, value)\
+ return make_integer (value)
+#else
+#define LISP_INTEGER_TO_C_TYPE(c_type, objekt) \
+ if (FIXNUMP (objekt)) \
+ do \
+ { \
+ EMACS_INT ival = XREALFIXNUM (objekt); \
+ \
+ if (sizeof (c_type) >= sizeof (EMACS_INT) ? \
+ ((c_type) ival < min_lisp_to_c_type || \
+ (c_type) ival > max_lisp_to_c_type) : \
+ (ival < (EMACS_INT) min_lisp_to_c_type || \
+ ival > (EMACS_INT) max_lisp_to_c_type)) \
+ { \
+ args_out_of_range_3 (objekt, \
+ make_float (min_lisp_to_c_type), \
+ make_float (max_lisp_to_c_type)); \
+ } \
+ \
+ return (c_type) ival; \
+ } while (0)
+
+#define C_TYPE_TO_LISP_INTEGER(c_type, value) \
+ if (NUMBER_FITS_IN_A_FIXNUM (value)) \
+ { \
+ return make_fixnum (value); \
+ } \
+ else \
+ { \
+ Lisp_Object result = Fcons (make_fixnum (value & 0xFFFF), Qnil); \
+ Boolint negative = value < 0; \
+ \
+ /* Only the most significant 16 bits will be negative in the \
+ constructed cons. */ \
+ value = (value >> 16); \
+ if (negative) \
+ { \
+ value = -value; \
+ } \
+ \
+ while (value) \
+ { \
+ value = value >> 16; \
+ result = Fcons (make_fixnum (value & 0xFFFF), result); \
+ } \
+ \
+ if (negative) \
+ { \
+ XSETCAR (result, make_fixnum (- (XFIXNUM (XCAR (result))))); \
+ } \
+ \
+ return result; \
+ } \
+ RETURN_NOT_REACHED ((c_type)-1)
+#endif
+
+#define DEFINE_C_INTEGER_TYPE_LISP_CONVERSION(visibility, c_type) \
+ visibility c_type \
+ lisp_to_##c_type (Lisp_Object objeto) \
+ { \
+ c_type min_lisp_to_c_type, max_lisp_to_c_type, result = 0; \
+ double dval; \
+ \
+ if (((c_type) -1) < 0) /* Signed type? */ \
+ { \
+ if (sizeof (c_type) == SIZEOF_SHORT) \
+ { \
+ max_lisp_to_c_type = (c_type) ((unsigned short) -1) / 2; \
+ min_lisp_to_c_type \
+ = (c_type) ((unsigned short)(max_lisp_to_c_type) + 1); \
+ } \
+ else if (sizeof (c_type) == SIZEOF_INT) \
+ { \
+ max_lisp_to_c_type = (c_type) ((unsigned int) -1) / 2; \
+ min_lisp_to_c_type \
+ = (c_type) ((unsigned int)(max_lisp_to_c_type) + 1); \
+ } \
+ else if (sizeof (c_type) == SIZEOF_LONG) \
+ { \
+ max_lisp_to_c_type = (c_type) (((unsigned long) -1) / 2); \
+ min_lisp_to_c_type \
+ = (c_type) ((unsigned long)(max_lisp_to_c_type) + 1); \
+ } \
+ else if (sizeof (c_type) == SIZEOF_LONG_LONG) \
+ { \
+ max_lisp_to_c_type \
+ = (c_type) (((unsigned long long) -1) / 2); \
+ min_lisp_to_c_type \
+ = (c_type) ((unsigned long long)(max_lisp_to_c_type) + 1); \
+ } \
+ else \
+ { \
+ assert (0); /* Very very very unlikely. */ \
+ } \
+ } \
+ else \
+ { \
+ min_lisp_to_c_type = 0; \
+ max_lisp_to_c_type = (c_type)(-1); \
+ } \
+ \
+ LISP_INTEGER_TO_C_TYPE (c_type, objeto); \
+ \
+ if (CONSP (objeto)) \
+ { \
+ unsigned counter = 1; \
+ Lisp_Object orig = objeto; \
+ \
+ if ((c_type)-1 < 0) \
+ { \
+ check_integer_range (XCAR (objeto), make_fixnum (-32768), \
+ make_fixnum (32767)); \
+ } \
+ else \
+ { \
+ check_integer_range (XCAR (objeto), Qzero, \
+ make_fixnum (65535)); \
+ } \
+ \
+ result = XFIXNUM (XCAR (objeto)); \
+ objeto = XCDR (objeto); \
+ \
+ while (CONSP (objeto)) \
+ { \
+ check_integer_range (XCAR (objeto), Qzero, \
+ make_fixnum (65535)); \
+ counter++; \
+ if (counter > sizeof (c_type) / 2) \
+ { \
+ invalid_argument ("Too many bits supplied " \
+ "for " #c_type, \
+ orig); \
+ } \
+ result \
+ = (result << 16) | (XFIXNUM (XCAR (objeto)) & 0xFFFF); \
+ objeto = XCDR (objeto); \
+ } \
+ \
+ return result; \
+ } \
+ \
+ dval = extract_float (objeto); \
+ result = dval; \
+ \
+ if (result < min_lisp_to_c_type || result > max_lisp_to_c_type) \
+ { \
+ args_out_of_range_3 (objeto, make_float (min_lisp_to_c_type), \
+ make_float (max_lisp_to_c_type)); \
+ } \
+ \
+ if (dval != result) \
+ { \
+ invalid_argument ("Fractional or two wide " #c_type, \
+ objeto); \
+ } \
+ \
+ return result; \
+ } \
+ \
+ visibility Lisp_Object \
+ c_type##_to_lisp (c_type value) \
+ { \
+ C_TYPE_TO_LISP_INTEGER (c_type, value); \
+ } \
+ visibility Lisp_Object c_type##_to_lisp (c_type)
+
+DEFINE_C_INTEGER_TYPE_LISP_CONVERSION (extern, OFF_T);
+
+DEFINE_C_INTEGER_TYPE_LISP_CONVERSION (extern, uid_t);
+
/************************************************************************/
/* initialization */
/************************************************************************/
diff -r 368318a5c386 -r 046a3f85a39d src/dired.c
--- a/src/dired.c
+++ b/src/dired.c
@@ -838,13 +838,13 @@
Lisp_Object directory = Qnil;
struct stat s;
char modes[10];
- Lisp_Object handler, mode, modestring = Qnil, size, gid;
- struct gcpro gcpro1, gcpro2, gcpro3;
+ Lisp_Object handler, mode, modestring = Qnil, size = Qzero, gid;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object uidInfo = Qnil;
Lisp_Object gidInfo = Qnil;
- GCPRO3 (filename, directory, modestring);
+ GCPRO4 (filename, directory, modestring, size);
filename = Fexpand_file_name (filename, Qnil);
/* If the file name has special constructs in it,
@@ -900,13 +900,7 @@
#endif
}
-#ifndef HAVE_BIGNUM
- size = make_fixnum (NUMBER_FITS_IN_A_FIXNUM (s.st_size) ?
- (EMACS_INT)s.st_size : -1);
-#else
- size = make_integer (s.st_size);
-#endif
-
+ size = OFF_T_to_lisp (s.st_size);
filemodestring (&s, modes);
modestring = make_string ((Ibyte *) modes, 10);
diff -r 368318a5c386 -r 046a3f85a39d src/editfns.c
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -604,7 +604,7 @@
if (!tmpdir)
{
struct stat st;
- int myuid = getuid ();
+ uid_t myuid = getuid ();
Ibyte *login_name = user_login_name (NULL);
DECLARE_EISTRING (eipath);
Ibyte *path;
@@ -614,7 +614,7 @@
path = eidata (eipath);
if (qxe_lstat (path, &st) < 0 && errno == ENOENT)
qxe_mkdir (path, 0700); /* ignore retval -- checked next anyway. */
- if (qxe_lstat (path, &st) == 0 && (int) st.st_uid == myuid
+ if (qxe_lstat (path, &st) == 0 && st.st_uid == myuid
&& S_ISDIR (st.st_mode))
tmpdir = path;
else
@@ -665,8 +665,7 @@
if (!NILP (uid))
{
- CHECK_FIXNUM (uid);
- local_uid = XFIXNUM (uid);
+ local_uid = lisp_to_uid_t (uid);
returned_name = user_login_name (&local_uid);
}
else
@@ -750,7 +749,7 @@
*/
())
{
- return make_fixnum (geteuid ());
+ return uid_t_to_lisp (geteuid ());
}
DEFUN ("user-real-uid", Fuser_real_uid, 0, 0, 0, /*
@@ -758,7 +757,7 @@
*/
())
{
- return make_fixnum (getuid ());
+ return uid_t_to_lisp (getuid ());
}
DEFUN ("user-full-name", Fuser_full_name, 0, 1, 0, /*
diff -r 368318a5c386 -r 046a3f85a39d src/fileio.c
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -166,54 +166,6 @@
}
return build_extstring (ret, Qstrerror_encoding);
}
-
-static OFF_T
-lisp_to_off_t (Lisp_Object offset)
-{
- OFF_T result;
- double v;
-
- if (FIXNUMP (offset))
- {
- type_checking_assert (FIXNUM_VALBITS <=
- (sizeof (OFF_T) * BITS_PER_CHAR));
- return XREALFIXNUM (offset);
- }
-#ifdef HAVE_BIGNUM
- if (BIGNUMP (offset))
- {
- if (bignum_fits_emacs_int_p (XBIGNUM_DATA (offset)))
- {
- type_checking_assert (BITS_PER_EMACS_INT <=
- (sizeof (OFF_T) * BITS_PER_CHAR));
- return bignum_to_emacs_int (XBIGNUM_DATA (offset));
- }
- else if (sizeof (OFF_T) == sizeof (long long)
- && bignum_fits_llong_p (XBIGNUM_DATA (offset)))
- {
- return bignum_to_llong (XBIGNUM_DATA (offset));
- }
- else if (sizeof (OFF_T) == sizeof (unsigned long long)
- && (OFF_T)(-1) != -1
- && bignum_fits_ullong_p (XBIGNUM_DATA (offset)))
- {
- return bignum_to_ullong (XBIGNUM_DATA (offset));
- }
- }
-#endif
-
- v = extract_float (offset);
- result = v;
-
- if (result == v) /* Value bits preserved? */
- {
- return result;
- }
-
- wtaerror ("Offset not supported", offset);
- RETURN_NOT_REACHED (-1);
-}
-
static Lisp_Object
close_file_unwind (Lisp_Object fd)
@@ -3025,7 +2977,7 @@
{
start = Qzero;
}
- else if (lisp_to_off_t (start) < 0)
+ else if (lisp_to_OFF_T (start) < 0)
{
start = wrong_type_argument (Qnatnump, start);
}
@@ -3207,7 +3159,7 @@
Lisp_Object args[] = { end, start };
Lisp_Object diff = Fminus (countof (args), args);
- total = lisp_to_off_t (diff);
+ total = lisp_to_OFF_T (diff);
if (total < 0)
{
@@ -3231,7 +3183,7 @@
where it should be. */
|| (!NILP (replace) && do_speedy_insert))
{
- if (lseek (fd, lisp_to_off_t (start), 0) < 0)
+ if (lseek (fd, lisp_to_OFF_T (start), 0) < 0)
report_file_error ("Setting file position", filename);
}
@@ -3567,7 +3519,7 @@
if (NUMBERP (append))
{
whence = SEEK_SET;
- offset = lisp_to_off_t (append);
+ offset = lisp_to_OFF_T (append);
if (offset < 0)
{
dead_wrong_type_argument (Qnatnump, append);
diff -r 368318a5c386 -r 046a3f85a39d src/number.h
--- a/src/number.h
+++ b/src/number.h
@@ -437,6 +437,12 @@
extern enum number_type get_number_type (Lisp_Object);
extern enum number_type promote_args (Lisp_Object *, Lisp_Object *);
+extern Lisp_Object OFF_T_to_lisp (OFF_T);
+extern OFF_T lisp_to_OFF_T (Lisp_Object);
+
+extern Lisp_Object uid_t_to_lisp (uid_t);
+extern uid_t lisp_to_uid_t (Lisp_Object);
+
#ifdef WITH_NUMBER_TYPES
/* promote_args() *always* converts a marker argument to a fixnum.
diff -r 368318a5c386 -r 046a3f85a39d tests/ChangeLog
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2018-04-21 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * automated/os-tests.el (two-to-the-thirty-second):
+ Check that (user-login-name 4294967296) no longer gives "root", as
+ it used to do on 64-bit builds.
+
2018-04-06 Aidan Kehoe <kehoea(a)parhasard.net>
* automated/os-tests.el (handle-call-process-cases): New.
diff -r 368318a5c386 -r 046a3f85a39d tests/automated/os-tests.el
--- a/tests/automated/os-tests.el
+++ b/tests/automated/os-tests.el
@@ -119,4 +119,14 @@
'(22803 29256))) ;; "05/10/17 09:04:24 PM"
(Check-Error args-out-of-range (encode-time 24 4 20 11 5 2017 86401))
+(let ((two-to-the-thirty-second (expt 2 32)))
+ (Skip-Test-Unless (and (integerp two-to-the-thirty-second)
+ (> two-to-the-thirty-second 0))
+ "No integers greater than #x3fffffff"
+ "Testing bit width confusion with underlying uid_t"
+ (Assert
+ (not (equal (ignore-errors
+ (user-login-name two-to-the-thirty-second))
+ "root")))))
+
;;; end of os-tests.el
Repository URL:
https://bitbucket.org/xemacs/xemacs/
--
This is a commit notification from
bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.