Hi all,

I noticed two problems after looking over the file-modification-time
patches I recently submitted.  The first is that on 32-bit systems, the
mtime or atime that the user passes in would get truncated to 32 bits
on a 32-bit platform (and presumably also on a 64-bit LLP platform, ie
64-bit Windows) due to using C_int_to_num instead of C_int_to_num64.

The other problem is related; size_t is an unsigned type, not a signed
type, and it can be 64-bit even on 32-bit systems, so we should better
use C_int_to_num64 for that type as well.

Attached are patches for this.

Strictly speaking, I suppose we should really add a new C_num_to_size_t
or such, but if we do that, we will need to add it for every stupid
opaque type that C might offer.  In practice, size_t is at most 64 bits
so let's just keep that assumption (for now?).

Cheers,
Peter
From 44a187085319c440d28402914ad8ba4ac7b62578 Mon Sep 17 00:00:00 2001
From: Peter Bex <pe...@more-magic.net>
Date: Tue, 6 Jun 2017 21:06:57 +0200
Subject: [PATCH 1/2] Do not truncate file times to 32 bits on 32-bit or LLP
 platforms in setter

---
 posixunix.scm | 4 ++--
 posixwin.scm  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/posixunix.scm b/posixunix.scm
index 54bfe7e..f20623e 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -370,12 +370,12 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
   if (atime == C_SCHEME_FALSE) {
     tb.actime = sb.st_atime;
   } else {
-    tb.actime = C_num_to_int(atime);
+    tb.actime = C_num_to_int64(atime);
   }
   if (mtime == C_SCHEME_FALSE) {
     tb.modtime = sb.st_mtime;
   } else {
-    tb.modtime = C_num_to_int(mtime);
+    tb.modtime = C_num_to_int64(mtime);
   }
   return utime(filename, &tb);
 }
diff --git a/posixwin.scm b/posixwin.scm
index 735504c..c0a2cf8 100644
--- a/posixwin.scm
+++ b/posixwin.scm
@@ -648,12 +648,12 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
   if (atime == C_SCHEME_FALSE) {
     tb.actime = sb.st_atime;
   } else {
-    tb.actime = C_num_to_int(atime);
+    tb.actime = C_num_to_int64(atime);
   }
   if (mtime == C_SCHEME_FALSE) {
     tb.modtime = sb.st_mtime;
   } else {
-    tb.modtime = C_num_to_int(mtime);
+    tb.modtime = C_num_to_int64(mtime);
   }
   return _utime(filename, &tb);
 }
-- 
2.1.4

From 95e19db09f94c222e97fb50e0e0e687a2f5a4cee Mon Sep 17 00:00:00 2001
From: Peter Bex <pe...@more-magic.net>
Date: Tue, 6 Jun 2017 21:28:21 +0200
Subject: [PATCH 2/2] Fix size_t to map to unsigned 64-bit integers, add signed
 ssize_t

Add a test case to ensure they can represent the proper range.
---
 NEWS                     |  5 +++++
 c-backend.scm            | 14 ++++++++------
 support.scm              | 17 ++++++++---------
 tests/compiler-tests.scm |  6 ++++++
 4 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/NEWS b/NEWS
index d179db0..f4b0e04 100644
--- a/NEWS
+++ b/NEWS
@@ -82,6 +82,11 @@
   - Static compilation of eggs is now fully supported and static
     versions of compiled eggs are available by default.
 
+- Foreign function interface
+  - The foreign type specifier "ssize_t" is now accepted, and "size_t"
+    arguments now only accept positive integers.  Return values of
+    type size_t are no longer truncated on 32-bit platforms.
+
 
 4.12.1
 
diff --git a/c-backend.scm b/c-backend.scm
index 1c0f8f2..6be88ab 100644
--- a/c-backend.scm
+++ b/c-backend.scm
@@ -1129,9 +1129,10 @@
 		   c-string-list c-string-list*)
 	    (string-append ns "+3") )
 	   ((unsigned-integer unsigned-integer32 long integer integer32 
-			      unsigned-long size_t number)
+			      unsigned-long number)
 	    (string-append ns "+C_SIZEOF_FIX_BIGNUM"))
-	   ((unsigned-integer64 integer64) ; On 32-bit systems, needs 2 digits
+	   ((unsigned-integer64 integer64 size_t ssize_t)
+	    ;; On 32-bit systems, needs 2 digits
 	    (string-append ns "+C_SIZEOF_BIGNUM(2)"))
 	   ((c-string c-string* unsigned-c-string unsigned-c-string unsigned-c-string*)
 	    (string-append ns "+2+(" var "==NULL?1:C_bytestowords(C_strlen(" var ")))") )
@@ -1203,6 +1204,7 @@
       ((unsigned-int32 unsigned-integer32) (str "C_u32"))
       ((int integer bool) (str "int"))
       ((size_t) (str "size_t"))
+      ((ssize_t) (str "ssize_t"))
       ((int32 integer32) (str "C_s32"))
       ((integer64) (str "C_s64"))
       ((unsigned-integer64) (str "C_u64"))
@@ -1303,7 +1305,8 @@
       ((double number float) "C_c_double(")
       ((integer integer32) "C_num_to_int(")
       ((integer64) "C_num_to_int64(")
-      ((size_t) "(size_t)C_num_to_int(")
+      ((size_t) "(size_t)C_num_to_uint64(")
+      ((ssize_t) "(ssize_t)C_num_to_int64(")
       ((unsigned-integer64) "C_num_to_uint64(")
       ((long) "C_num_to_long(")
       ((unsigned-integer unsigned-integer32) "C_num_to_unsigned_int(")
@@ -1384,9 +1387,8 @@
        (sprintf "C_mpointer(&~a,(void*)" dest) )
       ((c-pointer) (sprintf "C_mpointer_or_false(&~a,(void*)" dest))
       ((integer integer32) (sprintf "C_int_to_num(&~a," dest))
-      ((integer64) (sprintf "C_int64_to_num(&~a," dest))
-      ((size_t) (sprintf "C_int_to_num(&~a,(int)" dest)) ; XXX 64 bits?
-      ((unsigned-integer64) (sprintf "C_uint64_to_num(&~a," dest))
+      ((integer64 ssize_t) (sprintf "C_int64_to_num(&~a," dest))
+      ((unsigned-integer64 size_t) (sprintf "C_uint64_to_num(&~a," dest))
       ((unsigned-integer unsigned-integer32) (sprintf "C_unsigned_int_to_num(&~a," dest))
       ((long) (sprintf "C_long_to_num(&~a," dest))
       ((unsigned-long) (sprintf "C_unsigned_long_to_num(&~a," dest))
diff --git a/support.scm b/support.scm
index 2c04d2e..233ad96 100644
--- a/support.scm
+++ b/support.scm
@@ -975,7 +975,7 @@
 		 (integer64 . "C_s64") (unsigned-integer64 . "C_u64")
 		 (short . "short") (unsigned-short . "unsigned short")
 		 (long . "long") (unsigned-long . "unsigned long")
-		 (size_t . "size_t"))))
+		 (ssize_t . "ssize_t") (size_t . "size_t"))))
     (lambda (param type)
       (follow-without-loop
        type
@@ -1030,14 +1030,14 @@
 		  `(##sys#foreign-struct-wrapper-argument 
 		    ',(##sys#slot (assq t tmap) 1)
 		    ,param) ) )
-	     ((integer32 integer64 integer short long size_t)
+	     ((integer32 integer64 integer short long ssize_t)
 	      (let* ((foreign-type (##sys#slot (assq t ftmap) 1))
 		     (size-expr (sprintf "sizeof(~A) * CHAR_BIT" foreign-type)))
 		(if unsafe
 		    param
 		    `(##sys#foreign-ranged-integer-argument
 		      ,param (foreign-value ,size-expr int)))))
-	     ((unsigned-short unsigned-long unsigned-integer
+	     ((unsigned-short unsigned-long unsigned-integer size_t
 			      unsigned-integer32 unsigned-integer64)
 	      (let* ((foreign-type (##sys#slot (assq t ftmap) 1))
 		     (size-expr (sprintf "sizeof(~A) * CHAR_BIT" foreign-type)))
@@ -1155,11 +1155,11 @@
                   unsigned-c-string unsigned-c-string* nonnull-unsigned-c-string*
 		  c-string-list c-string-list*)
 	(words->bytes 3) )
-       ((unsigned-integer long integer size_t unsigned-long integer32 unsigned-integer32)
+       ((unsigned-integer long integer unsigned-long integer32 unsigned-integer32)
 	(words->bytes 6) )    ; 1 bignum digit on 32-bit (overallocs on 64-bit)
        ((float double number) 
 	(words->bytes 4) )		; possibly 8-byte aligned 64-bit double
-       ((integer64 unsigned-integer64)
+       ((integer64 unsigned-integer64 size_t ssize_t)
 	(words->bytes 7))     ; 2 bignum digits on 32-bit (overallocs on 64-bit)
        (else
 	(cond ((and (symbol? t) (lookup-foreign-type t))
@@ -1182,11 +1182,10 @@
        ((char int short bool unsigned-short unsigned-char unsigned-int long unsigned-long byte unsigned-byte
 	      c-pointer nonnull-c-pointer unsigned-integer integer float c-string symbol
 	      scheme-pointer nonnull-scheme-pointer int32 unsigned-int32 integer32 unsigned-integer32
-              unsigned-c-string unsigned-c-string* nonnull-unsigned-c-string* size_t
+              unsigned-c-string unsigned-c-string* nonnull-unsigned-c-string*
 	      nonnull-c-string c-string* nonnull-c-string* c-string-list c-string-list*)
 	(words->bytes 1) )
-       ;; XXX TODO FIXME: What is "number" doing here?
-       ((double number integer64 unsigned-integer64)
+       ((double integer64 unsigned-integer64 size_t ssize_t)
 	(words->bytes 2) )
        (else
 	(cond ((and (symbol? t) (lookup-foreign-type t))
@@ -1276,7 +1275,7 @@
       ((nonnull-s64vector) '(struct s64vector))
       ((nonnull-f32vector) '(struct f32vector))
       ((nonnull-f64vector) '(struct f64vector))
-      ((integer long size_t integer32 unsigned-integer32 integer64 unsigned-integer64
+      ((integer long size_t ssize_t integer32 unsigned-integer32 integer64 unsigned-integer64
 		unsigned-long) 
        'integer)
       ((c-pointer)
diff --git a/tests/compiler-tests.scm b/tests/compiler-tests.scm
index 9d92afc..d753bee 100644
--- a/tests/compiler-tests.scm
+++ b/tests/compiler-tests.scm
@@ -357,6 +357,12 @@
 (test-ffi-type-limits
  long signed (foreign-value "sizeof(long) * CHAR_BIT" int))
 
+(test-ffi-type-limits
+ ssize_t signed (foreign-value "sizeof(ssize_t) * CHAR_BIT" int))
+
+(test-ffi-type-limits
+ size_t unsigned (foreign-value "sizeof(size_t) * CHAR_BIT" int))
+
 
 ;; #1059: foreign vector types use wrong lolevel accessors, causing
 ;; paranoid DEBUGBUILD assertions to fail.
-- 
2.1.4

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers

Reply via email to