~ chicken-core (chicken-5) 21ff0d6affb35f7184a5e78f9d4beccc869b47b2


commit 21ff0d6affb35f7184a5e78f9d4beccc869b47b2
Author:     felix <felix@p.callcc.org>
AuthorDate: Sun Aug 25 12:23:05 2019 +0200
Commit:     Peter Bex <peter@more-magic.net>
CommitDate: Sat Sep 14 15:07:18 2019 +0200

    Disallow exporting variables defined with define-external
    
    When finalizing modules, explicitly check in compiled code whether
    the export refers to a variable defined with "define-external".
    Since such variables represent foreign memory, they do not follow Scheme
    semantics and any changes to them will not be reflected by an associated
    exported variable. Note that this is different for functions, these
    can not change spontaneously as compared to (say) a volatile external
    variable.
    
    Signed-off-by: Peter Bex <peter@more-magic.net>

diff --git a/NEWS b/NEWS
index e8cc6054..7d216375 100644
--- a/NEWS
+++ b/NEWS
@@ -31,6 +31,10 @@
   - Inline files no longer refer to unexported foreign stub functions
     (fixes #1440, thanks to "megane").
 
+- Module system
+  - Trying to export a foreign variable gives a friendly error instead
+    of saying the variable doesn't exist (partial fix for #1346).
+
 - Tools
   - The new "-module-registration" options causes module registration
     code to always be included in the program, even when it has also
diff --git a/core.scm b/core.scm
index bd36448b..9a51f04d 100644
--- a/core.scm
+++ b/core.scm
@@ -1019,7 +1019,9 @@
 						       ;; avoid backtrace
 						       (print-error-message ex (current-error-port))
 						       (exit 1))
-						   (##sys#finalize-module (##sys#current-module)))
+						   (##sys#finalize-module 
+                                                     (##sys#current-module)
+                                                     (map car foreign-variables)))
 						 (let ((il (or (assq name import-libraries) all-import-libraries)))
 						   (when il
 						     (emit-import-lib name il)
diff --git a/modules.scm b/modules.scm
index 6bbae798..aab5e6a5 100644
--- a/modules.scm
+++ b/modules.scm
@@ -446,7 +446,8 @@
 (define ##sys#finalize-module 
   (let ((display display)
 	(write-char write-char))
-    (lambda (mod)
+    (lambda (mod #!optional (bad-exports '())) 
+      ;; bad-exports: any list of symbols which should be rejected as invalid
       (let* ((explist (module-export-list mod))
 	     (name (module-name mod))
 	     (dlist (module-defined-list mod))
@@ -468,30 +469,33 @@
 		    '()
 		    (let* ((h (car xl))
 			   (id (if (symbol? h) h (car h))))
-		      (if (assq id sexports) 
-			  (loop (cdr xl))
-			  (cons 
-			   (cons 
-			    id
-			    (let ((def (assq id dlist)))
-			      (if (and def (symbol? (cdr def))) 
-				  (cdr def)
-				  (let ((a (assq id (##sys#current-environment))))
-				    (cond ((and a (symbol? (cdr a))) 
-					   (dm "reexporting: " id " -> " (cdr a))
-					   (cdr a)) 
-					  ((not def)
-					   (set! missing #t)
-					   (##sys#warn 
-					    (string-append 
-					     "exported identifier of module `" 
-					     (symbol->string name)
-					     "' has not been defined")
-					    id)
-					   #f)
-					  (else (module-rename id name)))))))
-			   (loop (cdr xl)))))))))
-	(for-each
+		      (cond ((assq id sexports) (loop (cdr xl)))
+                            ((memq id bad-exports)
+                             (##sys#error "special identifier may not be exported"
+                                          id))
+                            (else 
+                              (cons 
+                                (cons 
+			          id
+                                  (let ((def (assq id dlist)))
+                                    (if (and def (symbol? (cdr def))) 
+                                        (cdr def)
+                                        (let ((a (assq id (##sys#current-environment))))
+                                          (cond ((and a (symbol? (cdr a))) 
+                                                 (dm "reexporting: " id " -> " (cdr a))
+                                                 (cdr a)) 
+                                                ((not def)
+                                                 (set! missing #t)
+                                                 (##sys#warn 
+                                                   (string-append 
+					           "exported identifier of module `" 
+					           (symbol->string name)
+					           "' has not been defined")
+					           id)
+                                                 #f)
+                                                (else (module-rename id name)))))))
+                              (loop (cdr xl))))))))))
+        (for-each
 	 (lambda (u)
 	   (let* ((where (cdr u))
 		  (u (car u)))
Trap