macrobash |
I have committed a great sin: adding syntax macros to bash using read and eval. This document explains how to add syntax macros to bash, which is not an officially supported feature of bash, but is possible within bash. This means that macrobash is considered to be a different language than bash because the syntax changes. The type of macro I will be discussing is called a reader macro, and it works very simply. There is a bash command called read which can read from stdin or from a file. This means that the user may pipe text into bash, bash may read text from a file, or bash may read text directly from a user in the terminal. Because bash has regular expressions, bash may translate text into any other arbitrary text following rules. This means that bash can be used to write a compiler. This compiler translates machine code from one lanugage into bash following a set of rules. Once code is translated into bash it may be evaluated. Note about eval for seasonsed users: It is an old axiom never to evaluate code directly from the user. However this axiom is broken every day when users type coe into to the command prompt, which enters bash via stdin where it is then evaluated. The bash prompt evaluates one line of bash at a time. This is really no different from that. This isn't evaluation in the same sense as evaluating user input from a sql injection. You must implement macros which protect the user from SQL injection to the same degree or better that bash protects from it. In other words there is a way to do this in that it adds risk to bash and there is a way to do this where it does not add any, and there is a way to do this where it takes risk away. An example of a simple macro would be something like this: I would really like there to be a feature in bash to shorten the piece of code - "$HOME" - and I can not think of a suitable one. There is the ~ character, but my family was attacked by a ~ character when I was a child, and so I would like another way to do this. I can make a macro in bash which takes a literal 😀 character in unicode, and wherever it sees this character to replace this character with "$HOME". Then I can pass that macro over every line of bash which I evaluate to ensure that this is added as a piece of syntax in the code. That simple macro is not intended to replace bash as a new language. Technically bash does not have a "formal specification" but since the bash project does not support the 😀 character to mean "$HOME" this technically makes this variant of bash an entirely different language, which is to be expected. I will note though that this language is backwards compatible with bash. It only does very sane things to the syntax of bash. Let's look at a macro which does something insane to bash: A macro which replaces the "$*" with $* on every line. That kind of macro might only make sense to an experienced user, but it should be very clear to any seasoned user that this is a very bad idea to add to bash. In fact, this is an attack vector. Any kind of macro bash should be designed so that this would only happen if the user intended it to happen. It should be as difficult as is reasonable for a foreign attacker to add this macro to bash. Here I will clearly define what it looks like to properly add macros: 1. The program must read from stdin to check if being launched from a login or nonlogin shell and if the user wants to first parse from a file. 1.a If the user desires to read from a file, that file must be parsed using regex then evaluated. 2. If the exit command was not used, then the program should now start reading from stdin. 3. Each line from stdin must be parsed using a regex then evaluated. note: not all lines can be evaluated "immediately". For example, when using an if statement bash expects there to be more lines of code which. come after until the then and fi features are used. This means that the way in which your macro system is parsed must be able to detect it's depth such that if it is five if statments deep it should be contextually aware of it's own scope. In conclusion: Although the bash project does not officially support this, modern versions of bash and sh are totally capable of using syntactic macros, as are most shells. The ability to do this creates huge issues that are not easily solved. This is not a "good" thing. Just an interesting one. This makes bash much more complicated than it already is. |