Confine untrusted spec strings and identifiers inside Kotlin/Gradle literals
ober
ccbaa93cdb7bc0ea9a7b43966bd2268cb55cb2e9
--- a/jandroid.ss +++ b/jandroid.ss @@ -281,7 +281,27 @@ (if (state-entry? item) #f item)) '(column))) -(def (kotlin-ident sym) (symbol->string sym)) +(def (kotlin-identifier? text) + (and (string? text) + (> (string-length text) 0) + (<= (string-length text) 128) + (let ((first (string-ref text 0))) + (or (char-alphabetic? first) (char=? first #\_))) + (every (lambda (ch) + (or (char-alphabetic? ch) + (char-numeric? ch) + (char=? ch #\_))) + (string->list text)))) + +(def (kotlin-ident sym) + (let ((text (symbol->string sym))) + (unless (kotlin-identifier? text) + (error 'kotlin-ident "unsafe Kotlin identifier" text)) + text)) + +(def (control-char? ch) + (let ((code (char->integer ch))) + (or (< code 32) (= code 127)))) (def (escape-string s quote-ch) (with-output-to-string @@ -292,6 +312,11 @@ ((char=? ch #\\) (display "\\\\")) ((char=? ch #\newline) (display "\\n")) ((char=? ch #\tab) (display "\\t")) + ((char=? ch #\return) (display "\\r")) + ((char=? ch #\$) (display "${'$'}")) + ((control-char? ch) + (error 'escape-string "control character in string literal" + (char->integer ch))) (else (display ch))))))) (def (kotlin-string s) (string-append "\"" (escape-string s #\") "\"")) @@ -560,12 +585,37 @@ deps)) "}\n")))) +(def (gradle-property-key? value) + (and (string? value) + (> (string-length value) 0) + (<= (string-length value) 128) + (every (lambda (ch) + (or (char-alphabetic? ch) + (char-numeric? ch) + (char=? ch #\.) + (char=? ch #\_) + (char=? ch #\-))) + (string->list value)))) + +(def (gradle-property-value? value) + (and (string? value) + (<= (string-length value) 4096) + (every (lambda (ch) + (let ((code (char->integer ch))) + (and (>= code 32) (not (= code 127))))) + (string->list value)))) + (def (gradle-property-line property-form) (unless (and (= (length property-form) 3) (string? (cadr property-form)) (string? (caddr property-form))) (error 'gradle-property "expected `(gradle-property key value)`" property-form)) - (string-append (cadr property-form) "=" (caddr property-form) "\n")) + (let ((key (cadr property-form)) (value (caddr property-form))) + (unless (gradle-property-key? key) + (error 'gradle-property "unsafe gradle property key" key)) + (unless (gradle-property-value? value) + (error 'gradle-property "unsafe gradle property value" value)) + (string-append key "=" value "\n"))) (def (gradle-properties-file spec) (apply string-append (map gradle-property-line (gradle-property-forms spec))))