Bugs, incomplete things, things that could be done better, decisions that were not certain, etc. ==================== Address groups in mail headers are not yet handled. Address groups are the 'group:mailbox-list;' construct, such as 'undisclosed-recipient:;' ==================== While working on CUSP interface I noticed that the technique, used in e.g. $msgpart and $cdb functions, of hiding internal data along with the passed pointer that is returned to MFL -- this technique is flawed because it doesn't allow the MFL script to copy the pointer target to another variable and still let it work. I don't expect anyone to do that, and maybe they should be punished for trying, but anyway: CUSP does it better, and I now need to retrofit this method back to the other handle-returning/using functins. Although the CUSP method exposes some internal data to the MFL script, it uses less code. (Another option would be to have the internal data be an index into data that MFL script can't see.) Noted here so I will remember this, too. ==================== Bounce/reject handling is a difficult problem. In the current rev, an mvmda user can define an MFL hook ($hook_delivery_error) that will be called if there's an error. That hook can decide whether to request a rejection as a result of the delivery failure (and to limit that rejection to SMTP time only, although all that does is inhibit bounce). At the end of processing, the mvmda code may honor the bounce/reject flag that was requested earlier, subject to some other antibounce tests. There's really no great answer to how to handle delivery failures when the delivery is not coupled to SMTP; even if delivery *is* coupled to SMTP, there are difficult problems in this regard (e.g. what about alias expansions? multiple delivery paths, only some of which fail? etc). If the mvmda user does not define $hook_delivery_error, a canned one is supplied: the default one supresses *all* bounces, which may be just as wrong as generating them. At least some control is given to the script user here, and I'll continue to work on other solutions, (including mvmtr). Some feedback and ideas would help. ==================== No effort has been made to deal with UTF-8 comparisons etc. ==================== Similarly, support for a small set of different comparators/collations is hardwired into the C code. Ideally this should be made more dynamic. ==================== No effort has been made to validate and adhere to formats required for structured headers per RFC2822. This needs to be done. ==================== Initializer list nesting should be checked at parse time. Unfortunately C initializer syntax is fuzzy because both these are legal: int a = {3}; int b = 3; i.e. the braces are optional; yet braces are not optional for aggregates, nor even for scalar members within aggregates. e.g.: typedef struct { int a, b; } TT; TT x = {1,2}; are ok, but these are not: TT y = 1,2; TT z = {{1},{2}}; which makes common parsing for a particular type difficult. ==================== Because the mfl access regimen only goes a finite number of levels (in most cases, 1), it's possible to end up with falsely persistent objects. e.g. in the case of a pointer to a struct itself containing pointers: if the pointer to struct is released, and it's the final release of the struct, the struct is freed but the pointers within the struct are not let go. This does not do harm but it is wrong. ==================== BUG: preprocessor expansion nit (noted 20041002) While a macro is expanded, it is "painted blue" so that it isn't eligible for expansion again, to avoid an endless expansion loop. For cases like this: #define XX XX + 3 or #define ZZ(b) b + 3 this works fine. However not these: #define XX 3 + XX #define ZZ ZZ -- when referenced, they cause an endless expansion. The reason: expansion is done by pushing the macro body onto the input stream. The end-of-stream handler is responsible for popping the macro body off and removing the "blue paint". The thing is, at the point where this happens, the tokenizer is still looking for the next character that might be part of the token it is accepting. By the time it sees the complete token and token is checked to see if it's a macro name, the blue paint is gone, and the macro is eligible for expansion again. This bug was introduced by turning the proprocessor inside out (see 20030902 in ChangeLog). This sounds kind of ugly to fix- will probably ignore it for now, but it does need fixing. ==================== preprocessor expansion incompatibility The preprocessor is not cpp-compatible, in that it does not prescan for macro arguments before rescanning for other macros. In: #define this(x) x #define one(a) this(a) #define two b,b If you reference one(two) you get the expansion "b,b". This is because mfl-pp marks the argument "b,b" and uses it wherever it occurs in the expansion. But to be cpp-compatible, the macro body is supposed to be expanded first (i.e. into "this(b,b)") and then rescanned for macro calls. "this(b,b)" should then fail because it's given two arguments instead of one. Not sure we really need to fix that, but it's there. ==================== Probably a bug: mfl doesn't check that "break" and "continue" statements are in context. "break" used outside of a loop scope will probably cause the program to exit (breaking the control of the outermost control). Ditto "continue." ==================== Probably not a bug, but annoying nonetheless: you can get some strange error messages when writing bad MFL code. For example, the error message "aggregate not DVS" may be entirely accurate, but it's hard for a script writer to know how to fix the script error that caused it. ==================== SIEVE classifies statements as "action" or "test" or "control" . "test" statements are supposed to be used within a control statement such as "if" or "anyof," where the test statement follows the control statement and is followed by a code block. MFL allows a "test" statement to appear anywhere, so that its result may be used. e.g.: if sieve { header :contains "From" "mem" } ... or int result; result = sieve { header :contains "From" "mem" }; It's the parsing of the control statement (e.g. "if") that's responsible for collecting the test statement that follows plus the following code block. For these reasons, the underlying parsing of "test" sieve statements doesn't check any before or after context. One fallout of this is that the parser allows such things as sieve { true true true } This should probably be fixed. ==================== The whole message/partial bugaboo. Dunno if this will ever be addressed. e.g. http://www.kb.cert.org/vuls/id/836088 rfc1344 ==================== One flaw, depending on your perspective, is in the interpretation of the parse tree. The parser builds a parse tree, and the C-based interpreter follows it by using the C context, the C program stack (and procedure call stack). It would probably be better to build a state machine interpreter that doesn't descend into the C call stack to execute the tree; this would allow easy saving of precompiled scripts. I may get to this one day, if it ever really matters. ====================