Skip to content

Commit

Permalink
CS: improve ".zo" link checking for struct types
Browse files Browse the repository at this point in the history
Racket CS generates unsafe code to inline struct operations like
allocation and field access. If a ".zo" file is out of date, inlined
code can be wrong and can trigger a crash. Guard against that by at
least checking the number of expcted fields for a struct type with
inlined operations.

This is still a long way from guarding against broken ".zo" files, but
it addresses the most common mismatch-induced crashes that I have
seen.
  • Loading branch information
mflatt committed Apr 30, 2024
1 parent 8b6f26f commit f2294a6
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 11 deletions.
2 changes: 1 addition & 1 deletion pkgs/base/info.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

;; In the Racket source repo, this version should change exactly when
;; "racket_version.h" changes:
(define version "8.13.0.2")
(define version "8.13.0.3")

(define deps `("racket-lib"
["racket" #:version ,version]))
Expand Down
16 changes: 13 additions & 3 deletions racket/src/cs/linklet.sls
Original file line number Diff line number Diff line change
Expand Up @@ -1020,10 +1020,20 @@
(when (eq? (variable-val var) variable-undefined)
(raise-linking-failure "is uninitialized" target-inst inst sym))
(let ([v (if import-abi
;; The import ABI encoding is generated by schemify and checked here.
;; Currently, an ABI requirement specifies 'proc, a number of fields for
;; a structure type, or #t for "any values"
(let ([v (variable-val var)])
(when (eq? import-abi 'proc)
(unless (#%procedure? v)
(raise-linking-failure "was expected to have a procedure value" target-inst inst sym)))
(cond
[(eq? import-abi 'proc)
(unless (#%procedure? v)
(raise-linking-failure "was expected to have a procedure value" target-inst inst sym))]
[(fixnum? import-abi)
(let ([v (unsafe-strip-impersonator v)])
(unless (and (record-type-descriptor? v)
(eqv? import-abi (#%$record-type-field-count v)))
(raise-linking-failure (#%format "was expected to have a struct-type value with ~a fields" import-abi)
target-inst inst sym)))])
v)
var)])
(cons v
Expand Down
6 changes: 5 additions & 1 deletion racket/src/cs/schemified/schemify.scm

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 12 additions & 5 deletions racket/src/schemify/schemify.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,18 @@
(and im-ready?
(let ([k (import-group-lookup grp (import-ext-id im))])
(and (known-constant? k)
(if (known-procedure? k)
;; A call to the procedure is probably in unsafe form:
'proc
;; Otherwise, accept any value:
#t))))))
(cond
[(known-procedure? k)
;; A call to the procedure is probably in unsafe form:
'proc]
[(known-struct-type? k)
;; Struct-type operations turn into references of the struct type
;; and unsafe accesses based on a known size, so make sure the size
;; hasn't changed
(known-struct-type-field-count k)]
[else
;; Otherwise, accept any value:
#t]))))))
;; Convert internal to external identifiers for known-value info
(for/fold ([knowns (hasheq)]) ([ex-id (in-list ex-ids)])
(define id (ex-int-id ex-id))
Expand Down
2 changes: 1 addition & 1 deletion racket/src/version/racket_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define MZSCHEME_VERSION_X 8
#define MZSCHEME_VERSION_Y 13
#define MZSCHEME_VERSION_Z 0
#define MZSCHEME_VERSION_W 2
#define MZSCHEME_VERSION_W 3

/* A level of indirection makes `#` work as needed: */
#define AS_a_STR_HELPER(x) #x
Expand Down

0 comments on commit f2294a6

Please sign in to comment.