diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-08-21 08:08:41 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-08-21 08:12:13 -0700 |
commit | ff16e04f57347e5a327099a61f8b16d5ba50abf3 (patch) | |
tree | 1e1bc7ed285652e10e6f9227ea0cd4bf242866fb | |
parent | e440e3e06efddb2cb6a821df32a3e07cd748bf8a (diff) | |
download | mu-ff16e04f57347e5a327099a61f8b16d5ba50abf3.tar.gz |
3237
More checks for unsafe filesystem primitives. Most important, make sure the product of any $close-file instruction is never ignored, and that it's the same variable as the ingredient. (No way to indicate that in Mu code yet, but then Mu code should always be safe and not require such checks.)
-rw-r--r-- | 087file.cc | 36 | ||||
-rw-r--r-- | 088file.mu | 4 |
2 files changed, 38 insertions, 2 deletions
diff --git a/087file.cc b/087file.cc index 6db0008d..b9a16e94 100644 --- a/087file.cc +++ b/087file.cc @@ -23,6 +23,14 @@ case _OPEN_FILE_FOR_READING: { raise << maybe(get(Recipe, r).name) << "first ingredient of '$open-file-for-reading' should be a string, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); break; } + if (SIZE(inst.products) != 1) { + raise << maybe(get(Recipe, r).name) << "'$open-file-for-reading' requires exactly one product, but got '" << inst.original_string << "'\n" << end(); + break; + } + if (!is_mu_number(inst.products.at(0))) { + raise << maybe(get(Recipe, r).name) << "first product of '$open-file-for-reading' should be a number (file handle), but got '" << to_string(inst.products.at(0)) << "'\n" << end(); + break; + } break; } :(before "End Primitive Recipe Implementations") @@ -50,6 +58,14 @@ case _OPEN_FILE_FOR_WRITING: { raise << maybe(get(Recipe, r).name) << "first ingredient of '$open-file-for-writing' should be a string, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); break; } + if (SIZE(inst.products) != 1) { + raise << maybe(get(Recipe, r).name) << "'$open-file-for-writing' requires exactly one product, but got '" << inst.original_string << "'\n" << end(); + break; + } + if (!is_mu_number(inst.products.at(0))) { + raise << maybe(get(Recipe, r).name) << "first product of '$open-file-for-writing' should be a number (file handle), but got '" << to_string(inst.products.at(0)) << "'\n" << end(); + break; + } break; } :(before "End Primitive Recipe Implementations") @@ -76,6 +92,14 @@ case _READ_FROM_FILE: { raise << maybe(get(Recipe, r).name) << "first ingredient of '$read-from-file' should be a number, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); break; } + if (SIZE(inst.products) != 1) { + raise << maybe(get(Recipe, r).name) << "'$read-from-file' requires exactly one product, but got '" << inst.original_string << "'\n" << end(); + break; + } + if (!is_mu_character(inst.products.at(0))) { + raise << maybe(get(Recipe, r).name) << "first product of '$read-from-file' should be a character, but got '" << to_string(inst.products.at(0)) << "'\n" << end(); + break; + } break; } :(before "End Primitive Recipe Implementations") @@ -125,6 +149,10 @@ case _WRITE_TO_FILE: { raise << maybe(get(Recipe, r).name) << "second ingredient of '$write-to-file' should be a character, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); break; } + if (!inst.products.empty()) { + raise << maybe(get(Recipe, r).name) << "'$write-to-file' writes to no products, but got '" << inst.original_string << "'\n" << end(); + break; + } break; } :(before "End Primitive Recipe Implementations") @@ -165,6 +193,14 @@ case _CLOSE_FILE: { raise << maybe(get(Recipe, r).name) << "first ingredient of '$close-file' should be a number, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); break; } + if (SIZE(inst.products) != 1) { + raise << maybe(get(Recipe, r).name) << "'$close-file' requires exactly one product, but got '" << inst.original_string << "'\n" << end(); + break; + } + if (inst.products.at(0).name != inst.ingredients.at(0).name) { + raise << maybe(get(Recipe, r).name) << "'$close-file' requires its product to be the same as its ingredient, but got '" << inst.original_string << "'\n" << end(); + break; + } break; } :(before "End Primitive Recipe Implementations") diff --git a/088file.mu b/088file.mu index 2eeeec2c..b18919d0 100644 --- a/088file.mu +++ b/088file.mu @@ -51,7 +51,7 @@ def transmit-from-file file:number, sink:address:sink:character -> sink:address: loop } sink <- close sink - $close-file file + file <- $close-file file ] def transmit-from-text contents:address:array:character, sink:address:sink:character -> sink:address:sink:character [ @@ -87,5 +87,5 @@ def transmit-to-file file:number, source:address:source:character -> file:number $write-to-file file, c loop } - $close-file file + file <- $close-file file ] |