* lexbind ready for merge @ 2011-03-29 21:44 Stefan Monnier 2011-03-29 23:43 ` Daniel Colascione 2011-03-30 7:28 ` Tassilo Horn 0 siblings, 2 replies; 33+ messages in thread From: Stefan Monnier @ 2011-03-29 21:44 UTC (permalink / raw) To: emacs-devel OK, so AFAIK the lexbind branch is pretty much ready for merge. The only issue is that I'm not sure it has seen as much testing as I'd like, but then that's largely because it hasn't been merged yet. So if I don't hear any screams until then, I plan to merge it into trunk over the week-end or nearby. Stefan ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-29 21:44 lexbind ready for merge Stefan Monnier @ 2011-03-29 23:43 ` Daniel Colascione 2011-03-30 1:22 ` Stefan Monnier 2011-03-30 7:28 ` Tassilo Horn 1 sibling, 1 reply; 33+ messages in thread From: Daniel Colascione @ 2011-03-29 23:43 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel On 3/29/2011 2:44 PM, Stefan Monnier wrote: > OK, so AFAIK the lexbind branch is pretty much ready for merge. > The only issue is that I'm not sure it has seen as much testing as > I'd like, but then that's largely because it hasn't been merged yet. > So if I don't hear any screams until then, I plan to merge it into trunk > over the week-end or nearby. Thanks. I've been looking forward to this for a while. Just a few comments (I might send patches for some of these things when I have time): - The elisp manual still claims in a variety of places that Emacs does not support closures - apply-partially should have a compiler-macro now that we can implement it very efficiently; also, funcall-partially. - It might be a good idea to remove the "Once Emacs 19 becomes standard..." comment from cl.el - Can lexical-let and lexical-let* be made a no-op when compiling lexbound code? Looking at cl.el, it appears they're still up their usual dirty tricks. - lexical-binding only applies to code evaluated by `eval-buffer' and `eval-region'?! So I can't make code evaluated by M-: lexbound? - It'd be nice to be able to write small pieces of lexical code in non-lexbound code, e.g., in the expansion of a macro that gets used by both lexbound and non-lexbound. What's the best way to do that? - The documentation claims that defun doesn't capture its lexical scope. In interpreted code, it does. (require 'cl) (let ((bar2 5)) (defun foo () (incf bar2) (message "hi: %s" bar2))) In compiled code, we do not capture the variable and instead warn about it. Instead, we should capture the variable. Common Lisp explicitly allows this use, and it's convenient in some cases. - Disassembling a closure reports closed-over variables as constants; they're not. - Do we really use a whole cons cell for each closed-over variable, even in compiled code? ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-29 23:43 ` Daniel Colascione @ 2011-03-30 1:22 ` Stefan Monnier 2011-03-30 4:10 ` Daniel Colascione 0 siblings, 1 reply; 33+ messages in thread From: Stefan Monnier @ 2011-03-30 1:22 UTC (permalink / raw) To: Daniel Colascione; +Cc: emacs-devel > - The elisp manual still claims in a variety of places that Emacs does not > support closures Pointers to offenders welcome. > - apply-partially should have a compiler-macro now that we can implement it > very efficiently; also, funcall-partially. The current definition of apply-partially is not too inefficient, actually. I don't know what funcall-partially would be like. And I don't like either of them: apply-partially is just a way to make it easy to build closures by hand without resorting to lexical-let and independently from lexical-binding, but once you use lexical-binding you're usually better off using a plain closure. > - It might be a good idea to remove the "Once Emacs 19 becomes standard..." > comment from cl.el Feel free to do that on the trunk, I don't think it's really related to lexbind. > - Can lexical-let and lexical-let* be made a no-op when compiling lexbound > code? Looking at cl.el, it appears they're still up their usual > dirty tricks. They can *almost* be turned into `let' and `let*', except that (lexical-let ((buffer-file-name 3)) ...) will bind buffer-file-name lexically whereas `let' will always bind it dynamically. We could either ignore those issues or try to handle them, but I'd rather just mark lexical-let obsolete. (Of course, there's also the difficulty for the macro to reliably determine whether the expansion will be run in lexical-binding or dynamic-binding mode). > - lexical-binding only applies to code evaluated by `eval-buffer' and > eval-region'?! So I can't make code evaluated by M-: lexbound? ?!? AFAIK, M-: uses lexical or dynamic scoping according to the value of lexical-binding in the current buffer. > - It'd be nice to be able to write small pieces of lexical code in > non-lexbound code, e.g., in the expansion of a macro that gets used by both > lexbound and non-lexbound. Yes, it'd be nice. > What's the best way to do that? Currently, I think the best way to do that is to add the feature to the byte-compiler. The most promising avenue for it might be to use code of the form ((closure () <formalargs> <lexbindcode>) <actualargs>) and compile efficiently (I think currently such code will either result in a complaint about a malformed function, or else will leave the function uncompiled). > - The documentation claims that defun doesn't capture its lexical scope. In > interpreted code, it does. > (require 'cl) > (let ((bar2 5)) > (defun foo () > (incf bar2) > (message "hi: %s" bar2))) > In compiled code, we do not capture the variable and instead warn about it. > Instead, we should capture the variable. Yup. > Common Lisp explicitly allows this use, and it's convenient in > some cases. If you need it you can use (let ((bar2 5)) (defalias 'foo (lambda () "Foo." (incf bar2) (message "hi: %s" bar2)))) IIRC, the reason why defun doesn't work for it is fundamentally linked to some silly technicality, but I justify it for myself by the fact that all the "defun within a non-empty context" I've seen were bogus, so I'm not strongly motivated to handle it right. > - Disassembling a closure reports closed-over variables as constants; > they're not. They are. > - Do we really use a whole cons cell for each closed-over variable, even in > compiled code? Yes, tho only for variables which are mutated (yup, `setq' is costly). Stefan ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 1:22 ` Stefan Monnier @ 2011-03-30 4:10 ` Daniel Colascione 2011-03-30 11:35 ` Juanma Barranquero 2011-03-30 14:26 ` Stefan Monnier 0 siblings, 2 replies; 33+ messages in thread From: Daniel Colascione @ 2011-03-30 4:10 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel On 3/29/2011 6:22 PM, Stefan Monnier wrote: >> - apply-partially should have a compiler-macro now that we can implement it >> very efficiently; also, funcall-partially. > > The current definition of apply-partially is not too > inefficient, actually. I don't know what funcall-partially would > be like. And I don't like either of them: apply-partially is just a way > to make it easy to build closures by hand without resorting to > lexical-let and independently from lexical-binding, but once you use > lexical-binding you're usually better off using a plain closure. apply-partially at least involves less typing lexical-let, which (as I explain below) is required in some cases even with lexbind. As for funcall-partially: I never really liked how apply-partially differs from apply. The latter treats its last argument specially, while the former does not. If I had my way, I'd rename the current apply-partially to funcall-partially (or partial-funcall?) and create a new apply-partially that unpacks its last argument. But it probably can't be changed now... >> - It might be a good idea to remove the "Once Emacs 19 becomes standard..." >> comment from cl.el > > Feel free to do that on the trunk, I don't think it's really related > to lexbind. If I could, I would. :-) >> - Can lexical-let and lexical-let* be made a no-op when compiling lexbound >> code? Looking at cl.el, it appears they're still up their usual >> dirty tricks. > > They can *almost* be turned into `let' and `let*', except that > (lexical-let ((buffer-file-name 3)) ...) will bind buffer-file-name > lexically whereas `let' will always bind it dynamically. We could > either ignore those issues or try to handle them, but I'd rather just > mark lexical-let obsolete. I'd prefer to ignore the issues for now and transform lexical-let to let when lexical-binding is on, generating a compiler error if we're trying to lexically bind a special variable. I don't think many people try to do that. A macro that uses a lexical binding in its generated code still needs to use lexical-let in order for its generated form to work properly in either environment, and even outside macros, making lexical-let cheap in the lexbound case gives us a way to create backward-compatible code that automatically becomes more efficient in Emacs 24. > (Of course, there's also the difficulty for the macro to reliably > determine whether the expansion will be run in lexical-binding or > dynamic-binding mode). Wouldn't inspecting the value of lexical-binding work well enough? For evaluated code, the macro (regardless of how or whether it was compiled) will be called directly from the evaluator with the appropriate value of lexical-binding set. For compiled code, the macro will be called by the compiler with lexical-binding set to the value the compiler is using to compile the resulting form. The value of lexical-let at macro-run time and result-evaluation time *could* differ if the resulting form is squirreled away somewhere and reused later --- but I can't think of a case where that happens without the code being wrapped in some kind of function object that would capture the current value of lexical-let. Of course, you can lie: (defmacro* with-broken-code (&body body) (let (lexical-binding) (macroexpand-all `(progn ,@body))) That kind of thing is firmly in "It hurts when I do this" territory though. > >> - lexical-binding only applies to code evaluated by `eval-buffer' and >> eval-region'?! So I can't make code evaluated by M-: lexbound? > > ?!? AFAIK, M-: uses lexical or dynamic scoping according to the value > of lexical-binding in the current buffer. It does, but the documentation string still gives me the impression that it wouldn't be. Why isn't lexical-binding respected for all evaluation? >> - It'd be nice to be able to write small pieces of lexical code in >> non-lexbound code, e.g., in the expansion of a macro that gets used by both >> lexbound and non-lexbound. > > Yes, it'd be nice. > >> What's the best way to do that? > > Currently, I think the best way to do that is to add the feature to the > byte-compiler. The most promising avenue for it might be to use code > of the form ((closure ()<formalargs> <lexbindcode>)<actualargs>) and > compile efficiently (I think currently such code will either result in > a complaint about a malformed function, or else will leave the function > uncompiled). Ah, I see what you mean. Would a with-lexical-scope form suffice? ;; with-lexical-scope is itself compiled with lexical-binding t (defmacro* with-lexical-scope (&body body) (let* ((vars (remove-if (lambda (var) (or (special-variable-p var) (not (boundp var)))) (find-free-vars `(progn ,@body)))) (closure `(closure (t) ; no environment ,@args ,@body))) `(funcall ,closure ,@vars))) (defvar b 42) (defun some-dynamic-function (a) (with-lexical-scope (lambda (c) (+ a b c))) ;; or even (with-lexical-scope (defun foo (arg) ...)) That's not the same as (defun foo (arg) (with-lexical-scope ...))) because the argument binding strategies differ. >> - The documentation claims that defun doesn't capture its lexical scope. In >> interpreted code, it does. > >> (require 'cl) >> (let ((bar2 5)) >> (defun foo () >> (incf bar2) >> (message "hi: %s" bar2))) > >> In compiled code, we do not capture the variable and instead warn about it. >> Instead, we should capture the variable. > > Yup. > >> Common Lisp explicitly allows this use, and it's convenient in >> some cases. > > If you need it you can use > > (let ((bar2 5)) > (defalias 'foo (lambda () > "Foo." > (incf bar2) > (message "hi: %s" bar2)))) > > IIRC, the reason why defun doesn't work for it is fundamentally linked > to some silly technicality, but I justify it for myself by the fact that > all the "defun within a non-empty context" I've seen were bogus, so I'm > not strongly motivated to handle it right. Even if it's not particularly common, being consistent with Common Lisp and having fewer special cases are good things. Some people use constructs like this to create module-private variables (which is a bad idea, but that doesn't stop people doing it.) >> - Disassembling a closure reports closed-over variables as constants; >> they're not. > > They are. Err, yes. They are. >> - Do we really use a whole cons cell for each closed-over variable, even in >> compiled code? > > Yes, tho only for variables which are mutated (yup, `setq' is costly). Couldn't we create a box type, which would would be like a cons except that it'd hold just one value? (The #<foo> read-syntax is available.) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 4:10 ` Daniel Colascione @ 2011-03-30 11:35 ` Juanma Barranquero 2011-03-30 13:24 ` lexbind: how to replace lexical-let approach to hide secrets (was: lexbind ready for merge) Ted Zlatanov 2011-03-30 15:09 ` lexbind ready for merge Daniel Colascione 2011-03-30 14:26 ` Stefan Monnier 1 sibling, 2 replies; 33+ messages in thread From: Juanma Barranquero @ 2011-03-30 11:35 UTC (permalink / raw) To: Daniel Colascione; +Cc: Stefan Monnier, emacs-devel On Wed, Mar 30, 2011 at 06:10, Daniel Colascione <dan.colascione@gmail.com> wrote: > Even if it's not particularly common, being consistent with Common Lisp and > having fewer special cases are good things. Some people use constructs like > this to create module-private variables (which is a bad idea, but that > doesn't stop people doing it.) Why a bad idea? It's a common idiom for private, persistent variables. Juanma ^ permalink raw reply [flat|nested] 33+ messages in thread
* lexbind: how to replace lexical-let approach to hide secrets (was: lexbind ready for merge) 2011-03-30 11:35 ` Juanma Barranquero @ 2011-03-30 13:24 ` Ted Zlatanov 2011-03-30 21:12 ` lexbind: how to replace lexical-let approach to hide secrets Stefan Monnier 2011-03-30 15:09 ` lexbind ready for merge Daniel Colascione 1 sibling, 1 reply; 33+ messages in thread From: Ted Zlatanov @ 2011-03-30 13:24 UTC (permalink / raw) To: emacs-devel On Wed, 30 Mar 2011 13:35:56 +0200 Juanma Barranquero <lekktu@gmail.com> wrote: JB> On Wed, Mar 30, 2011 at 06:10, Daniel Colascione JB> <dan.colascione@gmail.com> wrote: >> Even if it's not particularly common, being consistent with Common Lisp and >> having fewer special cases are good things. Some people use constructs like >> this to create module-private variables (which is a bad idea, but that >> doesn't stop people doing it.) JB> Why a bad idea? It's a common idiom for private, persistent variables. Slightly related: auth-source.el uses `lexical-let' to define lambda accessors for secrets (so printing them, for instance, won't show a password). Will the secrets still be hidden in the lexbind branch? And is there a smarter way to do it? Sample code: (let ((data "my secret")) (lexical-let ((data data)) (lambda () data))) Thanks Ted ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind: how to replace lexical-let approach to hide secrets 2011-03-30 13:24 ` lexbind: how to replace lexical-let approach to hide secrets (was: lexbind ready for merge) Ted Zlatanov @ 2011-03-30 21:12 ` Stefan Monnier 2011-03-30 21:56 ` David Kastrup 2011-03-31 15:42 ` Ted Zlatanov 0 siblings, 2 replies; 33+ messages in thread From: Stefan Monnier @ 2011-03-30 21:12 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > Slightly related: auth-source.el uses `lexical-let' to define lambda > accessors for secrets (so printing them, for instance, won't show a > password). Will the secrets still be hidden in the lexbind branch? Using lexbind, yes. Using `let', no. > And > is there a smarter way to do it? > Sample code: > (let ((data "my secret")) > (lexical-let ((data data)) (lambda () data))) When lexical-binding is set: (let ((data "my secret")) (lambda () data)) returns something like (closure ((data . "my secret") t) () data). If you wan to hide the value, then use: (let ((data (let ((sym (make-symbol "foo"))) (set sym "secret") sym))) (lambda () (symbol-value data))) which is similar to the what lexical-let ends up doing. Stefan ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind: how to replace lexical-let approach to hide secrets 2011-03-30 21:12 ` lexbind: how to replace lexical-let approach to hide secrets Stefan Monnier @ 2011-03-30 21:56 ` David Kastrup 2011-03-30 22:29 ` Daniel Colascione 2011-03-31 15:42 ` Ted Zlatanov 1 sibling, 1 reply; 33+ messages in thread From: David Kastrup @ 2011-03-30 21:56 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > When lexical-binding is set: > > (let ((data "my secret")) > (lambda () data)) > > returns something like (closure ((data . "my secret") t) () data). > If you wan to hide the value, then use: > > (let ((data (let ((sym (make-symbol "foo"))) > (set sym "secret") > sym))) > (lambda () (symbol-value data))) > > which is similar to the what lexical-let ends up doing. All of which, by necessity, contain the necessary material to get at the secret in the bytecode/closure/funcell. Where, of course, it is reasonable easy to retrieve it. And that is actually overkill, since you can always just call that closure. Anybody care to tell me what the point of this exercise is actually supposed to be? -- David Kastrup ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind: how to replace lexical-let approach to hide secrets 2011-03-30 21:56 ` David Kastrup @ 2011-03-30 22:29 ` Daniel Colascione 0 siblings, 0 replies; 33+ messages in thread From: Daniel Colascione @ 2011-03-30 22:29 UTC (permalink / raw) To: David Kastrup; +Cc: emacs-devel On 3/30/2011 2:56 PM, David Kastrup wrote: > Stefan Monnier<monnier@iro.umontreal.ca> writes: > >> When lexical-binding is set: >> >> (let ((data "my secret")) >> (lambda () data)) >> >> returns something like (closure ((data . "my secret") t) () data). >> If you wan to hide the value, then use: >> >> (let ((data (let ((sym (make-symbol "foo"))) >> (set sym "secret") >> sym))) >> (lambda () (symbol-value data))) >> >> which is similar to the what lexical-let ends up doing. > > All of which, by necessity, contain the necessary material to get at the > secret in the bytecode/closure/funcell. Where, of course, it is > reasonable easy to retrieve it. And that is actually overkill, since > you can always just call that closure. > > Anybody care to tell me what the point of this exercise is actually > supposed to be? The idea is to prevent secrets being accidentally revealed in backtraces, lisp evaluation results, and so on. By the way: I didn't notice any secret erasure code in auth-source.el. Shouldn't someone somewhere do something like this? I didn't see anything in alloc.c that looks like it'd clear an object's bytes upon deallocation. (defun secure-erase-secret (my-secret) (dotimes (i (length my-secret)) (setf (aref my-secret i) 0))) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind: how to replace lexical-let approach to hide secrets 2011-03-30 21:12 ` lexbind: how to replace lexical-let approach to hide secrets Stefan Monnier 2011-03-30 21:56 ` David Kastrup @ 2011-03-31 15:42 ` Ted Zlatanov 2011-04-01 1:31 ` Stephen J. Turnbull 1 sibling, 1 reply; 33+ messages in thread From: Ted Zlatanov @ 2011-03-31 15:42 UTC (permalink / raw) To: emacs-devel On Wed, 30 Mar 2011 17:12:37 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> Slightly related: auth-source.el uses `lexical-let' to define lambda >> accessors for secrets (so printing them, for instance, won't show a >> password). Will the secrets still be hidden in the lexbind branch? SM> If you wan to hide the value, then use: SM> (let ((data (let ((sym (make-symbol "foo"))) SM> (set sym "secret") SM> sym))) SM> (lambda () (symbol-value data))) SM> which is similar to the what lexical-let ends up doing. I wonder if the above approach can simply replace the `lexical-let' macro in the lexbind branch. On Wed, 30 Mar 2011 23:56:59 +0200 David Kastrup <dak@gnu.org> wrote: DK> All of which, by necessity, contain the necessary material to get at the DK> secret in the bytecode/closure/funcell. Where, of course, it is DK> reasonable easy to retrieve it. And that is actually overkill, since DK> you can always just call that closure. DK> Anybody care to tell me what the point of this exercise is actually DK> supposed to be? 1) hide secrets so they are not printed when the auth-source return data structure is returned (as Daniel says below) 2) provide some abstraction for secrets so we can use something more secure when it's available in Emacs On Wed, 30 Mar 2011 15:29:12 -0700 Daniel Colascione <dan.colascione@gmail.com> wrote: DC> The idea is to prevent secrets being accidentally revealed in DC> backtraces, lisp evaluation results, and so on. DC> By the way: I didn't notice any secret erasure code in DC> auth-source.el. Shouldn't someone somewhere do something like this? I DC> didn't see anything in alloc.c that looks like it'd clear an object's DC> bytes upon deallocation. DC> (defun secure-erase-secret (my-secret) DC> (dotimes (i (length my-secret)) (setf (aref my-secret i) 0))) password-cache.el does something like this in ELisp. IMHO this should be done by Emacs; the core should provide a way to tag strings as "secret" so they are wiped on deallocation. I think this property should propagate when the string is copied. We can probably simulate some of this with closures but I think it would be 100 times cleaner at the C level. That way the consumer doesn't have to wipe the secret, just release it (but he should still be able to trigger the wipe explicitly if he knows he's done with the secret). Also the strings can then be stored in an encoded representation so it's not trivial to find them in memory. Ted ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind: how to replace lexical-let approach to hide secrets 2011-03-31 15:42 ` Ted Zlatanov @ 2011-04-01 1:31 ` Stephen J. Turnbull 2011-04-01 4:41 ` secret strings (was: lexbind: how to replace lexical-let approach to hide secrets) Ted Zlatanov 0 siblings, 1 reply; 33+ messages in thread From: Stephen J. Turnbull @ 2011-04-01 1:31 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel Ted Zlatanov writes: > IMHO this should be done by Emacs; the core should provide a way to tag > strings as "secret" so they are wiped on deallocation. I don't see why this is better than the method already used, since you would have to use a different call to make such strings. In the end it's up to the application to manage these secrets. > I think this property should propagate when the string is copied. But what about the storage the string is copied from? Really, keeping secrets is up to the application. I think this is overkill, and won't really help naive users keep their secrets. ^ permalink raw reply [flat|nested] 33+ messages in thread
* secret strings (was: lexbind: how to replace lexical-let approach to hide secrets) 2011-04-01 1:31 ` Stephen J. Turnbull @ 2011-04-01 4:41 ` Ted Zlatanov 2011-04-01 5:52 ` Stephen J. Turnbull 0 siblings, 1 reply; 33+ messages in thread From: Ted Zlatanov @ 2011-04-01 4:41 UTC (permalink / raw) To: emacs-devel On Fri, 01 Apr 2011 10:31:01 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: SJT> Ted Zlatanov writes: >> IMHO this should be done by Emacs; the core should provide a way to tag >> strings as "secret" so they are wiped on deallocation. SJT> I don't see why this is better than the method already used, since you SJT> would have to use a different call to make such strings. The consumer wouldn't have to explicitly track and clear such strings. I think this is better and *safer* than asking the consumer to do it. These strings would be made differently by the producer (the auth-source API in this case) using some Emacs core functionality. The consumer doesn't know they are different from ordinary strings. They print like normal strings. They simply get explicitly wiped on deallocation and *maybe* get stored in an obfuscated way. SJT> In the end it's up to the application to manage these secrets. I strongly disagree that the consumer should have to wipe secrets when done with them. That simply shifts the burden of managing secrets without easing it. >> I think this property should propagate when the string is copied. SJT> But what about the storage the string is copied from? Obviously data has to come from somewhere. It can come from the environment and from files and from IPC and from process pipes. Emacs can provide functions that read directly from those sources into a secret string. Again, this is to manage wipe on deallocation and maybe provide obfuscated storage, not a comprehensive security solution. I have no illusions that Emacs Lisp can ever be made secure and no desire to see that, either. SJT> I think this is overkill, and won't really help naive users keep SJT> their secrets. I'm not sure where "naive users" came into the picture and how we're supposed to help them with this proposal. It only benefits the consumer, which usually is an application, and the producer, which in my case is the auth-source API. Users should not see a difference or care. Hiding secrets from backtraces and printing is another matter. That we can do with `lexical-let' or the approach Stefan showed so I think it's a solved problem. I've changed the subject to reflect we're discussing "secret strings" now, though the name is not very good. Ted ^ permalink raw reply [flat|nested] 33+ messages in thread
* secret strings (was: lexbind: how to replace lexical-let approach to hide secrets) 2011-04-01 4:41 ` secret strings (was: lexbind: how to replace lexical-let approach to hide secrets) Ted Zlatanov @ 2011-04-01 5:52 ` Stephen J. Turnbull 2011-04-01 11:02 ` secret strings Ted Zlatanov 0 siblings, 1 reply; 33+ messages in thread From: Stephen J. Turnbull @ 2011-04-01 5:52 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel Ted Zlatanov writes: > SJT> In the end it's up to the application to manage these secrets. > > I strongly disagree that the consumer should have to wipe secrets when > done with them. That simply shifts the burden of managing secrets > without easing it. (defmacro with-secret-strings (variable-list &rest body) `(unwind-protect (progn ,@body) (mapc #'wipe-secret-string ,variable-list))) Was that so hard? > Obviously data has to come from somewhere. It can come from the > environment and from files and from IPC and from process pipes. Emacs > can provide functions that read directly from those sources into a > secret string. Sure. One for every such source .... > Hiding secrets from backtraces and printing is another matter. That we > can do with `lexical-let' or the approach Stefan showed so I think it's > a solved problem. I've changed the subject to reflect we're discussing > "secret strings" now, though the name is not very good. Well, I don't care about the name, but I don't see a use case where the users are really protected. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: secret strings 2011-04-01 5:52 ` Stephen J. Turnbull @ 2011-04-01 11:02 ` Ted Zlatanov 2011-04-01 14:38 ` Stephen J. Turnbull 2011-04-01 14:59 ` Stefan Monnier 0 siblings, 2 replies; 33+ messages in thread From: Ted Zlatanov @ 2011-04-01 11:02 UTC (permalink / raw) To: emacs-devel On Fri, 01 Apr 2011 14:52:05 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: SJT> Ted Zlatanov writes: SJT> In the end it's up to the application to manage these secrets. >> >> I strongly disagree that the consumer should have to wipe secrets when >> done with them. That simply shifts the burden of managing secrets >> without easing it. SJT> (defmacro with-secret-strings (variable-list &rest body) SJT> `(unwind-protect (progn ,@body) SJT> (mapc #'wipe-secret-string ,variable-list))) SJT> Was that so hard? I don't think that's the same thing. We want to pass the producer-generated data around and wipe it when the garbage collection deallocates the memory. But maybe I misunderstand something. >> Hiding secrets from backtraces and printing is another matter. That we >> can do with `lexical-let' or the approach Stefan showed so I think it's >> a solved problem. I've changed the subject to reflect we're discussing >> "secret strings" now, though the name is not very good. SJT> Well, I don't care about the name, but I don't see a use case where SJT> the users are really protected. It's a *convenience* so the consumer doesn't have to wipe the secret strings explicitly. I'm not proposing a security model; the user protection is only that there's a smaller chance an attacker would see the secret strings in a memory image of the Emacs process. If the secret strings are stored in an encrypted or obfuscated way, the chance becomes even smaller. The alternative way to do the above would be at the Lisp level. I think that would be slower, less convenient (requiring timers or manual wipe calls), and the chance of exposure would be greater. But it's certainly possible. It's how password-cache.el does it. Ted ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: secret strings 2011-04-01 11:02 ` secret strings Ted Zlatanov @ 2011-04-01 14:38 ` Stephen J. Turnbull 2011-04-01 15:12 ` Ted Zlatanov 2011-04-01 14:59 ` Stefan Monnier 1 sibling, 1 reply; 33+ messages in thread From: Stephen J. Turnbull @ 2011-04-01 14:38 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel Ted Zlatanov writes: > I'm not proposing a security model; the user protection is only > that there's a smaller chance an attacker would see the secret > strings in a memory image of the Emacs process. My point is, if you have no security model, why bother? It is very unlikely that an attack on Emacs memory would reveal "secret strings". If somebody cares about that small chance, they're either kidding themselves, or they have a security model that will tell them to *ignore* the autowiping GC, and wipe themselves. Cleanliness-is-next-to-***liness-ly y'rs, ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: secret strings 2011-04-01 14:38 ` Stephen J. Turnbull @ 2011-04-01 15:12 ` Ted Zlatanov 2011-04-01 16:14 ` Stephen J. Turnbull 0 siblings, 1 reply; 33+ messages in thread From: Ted Zlatanov @ 2011-04-01 15:12 UTC (permalink / raw) To: emacs-devel On Fri, 01 Apr 2011 23:38:20 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: SJT> Ted Zlatanov writes: >> I'm not proposing a security model; the user protection is only >> that there's a smaller chance an attacker would see the secret >> strings in a memory image of the Emacs process. SJT> My point is, if you have no security model, why bother? SJT> It is very unlikely that an attack on Emacs memory would reveal SJT> "secret strings". If somebody cares about that small chance, they're SJT> either kidding themselves, or they have a security model that will SJT> tell them to *ignore* the autowiping GC, and wipe themselves. OK. I'll buy that. So how, then, does the the producer, the auth-source API, encourage consumers to wipe their secrets? Should it set a timer (for a duration specified by the consumer) after which the secret gets wiped and 'wiped is returned instead? How can Emacs Lisp and maybe the new lexbind features help make this as seamless as possible for the consumer? On Fri, 01 Apr 2011 10:59:20 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> I don't think that's the same thing. We want to pass the >> producer-generated data around and wipe it when the garbage collection >> deallocates the memory. But maybe I misunderstand something. SM> I don't think that's what you want: work done by finalizers should never SM> be significant (e.g. it's a bad idea to use finalizers to close SM> file-handles, or to wipe sensitive data). If you want to wipe that SM> data, then do it explicitly with `clear-string', since the GC might SM> never collect it. OK, I understand. See my question above. Ted ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: secret strings 2011-04-01 15:12 ` Ted Zlatanov @ 2011-04-01 16:14 ` Stephen J. Turnbull 2011-04-01 20:08 ` Ted Zlatanov 0 siblings, 1 reply; 33+ messages in thread From: Stephen J. Turnbull @ 2011-04-01 16:14 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel Ted Zlatanov writes: > OK. I'll buy that. So how, then, does the the producer, the > auth-source API, encourage consumers to wipe their secrets? That depends on the security model, it seems to me. For some purposes, ROT13, with no secret at all, is sufficient "security". In other cases, the user is given a secret to be used once (eg, a temporary password). In other cases, the user may never see the secret at all (public key methods). The problem, as I see it, is that the auth-source doesn't know what the consumer is going to do with it, or how long the secret will remain valid. I don't really see how this is the auth-source's business. The `with-secret-strings' macro I suggested is the only fairly generic kind of thing I can think of, but it's not really very general. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: secret strings 2011-04-01 16:14 ` Stephen J. Turnbull @ 2011-04-01 20:08 ` Ted Zlatanov 2011-04-01 20:34 ` Stefan Monnier 0 siblings, 1 reply; 33+ messages in thread From: Ted Zlatanov @ 2011-04-01 20:08 UTC (permalink / raw) To: emacs-devel On Sat, 02 Apr 2011 01:14:16 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: SJT> Ted Zlatanov writes: >> OK. I'll buy that. So how, then, does the the producer, the >> auth-source API, encourage consumers to wipe their secrets? SJT> That depends on the security model, it seems to me. For some SJT> purposes, ROT13, with no secret at all, is sufficient "security". In SJT> other cases, the user is given a secret to be used once (eg, a SJT> temporary password). In other cases, the user may never see the SJT> secret at all (public key methods). OK. All the code is already written to hide it in a lexical closure. I think it's possible at least to encode the secret and decode it on the funcall. It will, obviously, still be somewhere in memory but at least not as visibly. Then the consumer can use `with-secret-strings' in their local scope. SJT> The problem, as I see it, is that the auth-source doesn't know what SJT> the consumer is going to do with it, or how long the secret will SJT> remain valid. I don't really see how this is the auth-source's SJT> business. It should at least try to hide secret data and help the consumer protect the secrets from accidental revealing (thus the secrets closure it uses currently). Good neighbors can warn you if you leave your door open, even if it's not strictly their business. SJT> The `with-secret-strings' macro I suggested is the only fairly generic SJT> kind of thing I can think of, but it's not really very general. I'll put it in auth-source.el and suggest it in auth.texi; I'll also crawl through the places that use auth-source and rewrite them to use the macro. So it will be useful--thank you for the suggestion. Ted ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: secret strings 2011-04-01 20:08 ` Ted Zlatanov @ 2011-04-01 20:34 ` Stefan Monnier 2011-04-01 21:25 ` Ted Zlatanov 0 siblings, 1 reply; 33+ messages in thread From: Stefan Monnier @ 2011-04-01 20:34 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > think it's possible at least to encode the secret and decode it on the > funcall. It will, obviously, still be somewhere in memory but at least Encoding/decoding is silly: it just hides the data, without storing it securely, so it's no better than the current "hide it behind a symbol&closure". I.e. more work wasted for no benefit. There are so many ways the data gets copied in memory during evaluation that encoding one string doesn't give you much guarantee that there isn't any copy of its content still lying around somewhere (for the same reason I consider clear-string to be only for use by the deluded). > It should at least try to hide secret data and help the consumer protect > the secrets from accidental revealing (thus the secrets closure it uses > currently). Good neighbors can warn you if you leave your door open, > even if it's not strictly their business. Note that instead of a closure, it can store the data in a symbol. That provides the same kind of protection (printing just prints the symbol), but is much more lightweight. Stefan ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: secret strings 2011-04-01 20:34 ` Stefan Monnier @ 2011-04-01 21:25 ` Ted Zlatanov 0 siblings, 0 replies; 33+ messages in thread From: Ted Zlatanov @ 2011-04-01 21:25 UTC (permalink / raw) To: emacs-devel On Fri, 01 Apr 2011 16:34:23 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> think it's possible at least to encode the secret and decode it on the >> funcall. It will, obviously, still be somewhere in memory but at least SM> Encoding/decoding is silly: it just hides the data, without storing it SM> securely, so it's no better than the current "hide it behind SM> a symbol&closure". I.e. more work wasted for no benefit. There are so SM> many ways the data gets copied in memory during evaluation that encoding SM> one string doesn't give you much guarantee that there isn't any copy of SM> its content still lying around somewhere (for the same reason I consider SM> clear-string to be only for use by the deluded). OK, if I can't store the data securely and Emacs can't help me do it, then I guess I'll note it in the auth.texi manual and move on. I hope you and the other Emacs developers will consider secret strings in the future in the context of a larger discussion about security in Emacs. >> It should at least try to hide secret data and help the consumer protect >> the secrets from accidental revealing (thus the secrets closure it uses >> currently). Good neighbors can warn you if you leave your door open, >> even if it's not strictly their business. SM> Note that instead of a closure, it can store the data in a symbol. SM> That provides the same kind of protection (printing just prints the SM> symbol), but is much more lightweight. True, but I think it's not a big difference (these are rarely created). The closure has the nice property that it has to be called and thus we can attach more behavior to it without affecting the consumer. Ted ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: secret strings 2011-04-01 11:02 ` secret strings Ted Zlatanov 2011-04-01 14:38 ` Stephen J. Turnbull @ 2011-04-01 14:59 ` Stefan Monnier 1 sibling, 0 replies; 33+ messages in thread From: Stefan Monnier @ 2011-04-01 14:59 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > I don't think that's the same thing. We want to pass the > producer-generated data around and wipe it when the garbage collection > deallocates the memory. But maybe I misunderstand something. I don't think that's what you want: work done by finalizers should never be significant (e.g. it's a bad idea to use finalizers to close file-handles, or to wipe sensitive data). If you want to wipe that data, then do it explicitly with `clear-string', since the GC might never collect it. Stefan ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 11:35 ` Juanma Barranquero 2011-03-30 13:24 ` lexbind: how to replace lexical-let approach to hide secrets (was: lexbind ready for merge) Ted Zlatanov @ 2011-03-30 15:09 ` Daniel Colascione 2011-03-30 15:20 ` Juanma Barranquero 1 sibling, 1 reply; 33+ messages in thread From: Daniel Colascione @ 2011-03-30 15:09 UTC (permalink / raw) To: Juanma Barranquero; +Cc: Stefan Monnier, emacs-devel [-- Attachment #1: Type: text/plain, Size: 778 bytes --] On 3/30/11 4:35 AM, Juanma Barranquero wrote: > On Wed, Mar 30, 2011 at 06:10, Daniel Colascione > <dan.colascione@gmail.com> wrote: > >> Even if it's not particularly common, being consistent with Common Lisp and >> having fewer special cases are good things. Some people use constructs like >> this to create module-private variables (which is a bad idea, but that >> doesn't stop people doing it.) > > Why a bad idea? It's a common idiom for private, persistent variables. Well, it's a great idea if you're into that kind of thing. Personally, I feel that having the ability to peer inside a module's state and see what's wrong is helpful, and truly private variables don't add much over having a naming convention that discourages casual modification. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 15:09 ` lexbind ready for merge Daniel Colascione @ 2011-03-30 15:20 ` Juanma Barranquero 0 siblings, 0 replies; 33+ messages in thread From: Juanma Barranquero @ 2011-03-30 15:20 UTC (permalink / raw) To: Daniel Colascione; +Cc: Stefan Monnier, emacs-devel On Wed, Mar 30, 2011 at 17:09, Daniel Colascione <dan.colascione@gmail.com> wrote: > Well, it's a great idea if you're into that kind of thing. I suppose yes, I'm "into that kind of thing", then. What can you expect from a guy whose languages of choice are Ada and Common Lisp? > Personally, > I feel that having the ability to peer inside a module's state and see > what's wrong is helpful, and truly private variables don't add much over > having a naming convention that discourages casual modification. Having private variables does not preclude peering inside, you just need accessors :-) As per naming conventions discouraging modification... Some users/programmers might see that as a challenge to overcome ;-) But anyway, my question was because your "bad idea" comment seemed to imply that private lexical variables were technically unsound, while is just that you don't like the style. Fair enough. Juanma ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 4:10 ` Daniel Colascione 2011-03-30 11:35 ` Juanma Barranquero @ 2011-03-30 14:26 ` Stefan Monnier 1 sibling, 0 replies; 33+ messages in thread From: Stefan Monnier @ 2011-03-30 14:26 UTC (permalink / raw) To: Daniel Colascione; +Cc: emacs-devel >> be like. And I don't like either of them: apply-partially is just a way >> to make it easy to build closures by hand without resorting to [...] > apply-partially at least involves less typing lexical-let, which (as Yes, I see we agree. > As for funcall-partially: I never really liked how apply-partially differs > from apply. The latter treats its last argument specially, while the former > does not. If I had my way, I'd rename the current apply-partially to > funcall-partially (or partial-funcall?) and create a new apply-partially > that unpacks its last argument. But it probably can't be changed now... I see your point. I chose the name `apply-partially' because in the functional programming community this is generally called a "partial application", but indeed it clashes somewhat with the use of `apply' in Lisp which doesn't just mean "function application". I think it's too late to fix it, tho. >>> - It might be a good idea to remove the "Once Emacs 19 becomes standard..." >>> comment from cl.el >> Feel free to do that on the trunk, I don't think it's really related >> to lexbind. > If I could, I would. :-) Why don't you request write access via Savannah? That would also make it easier for you to maintain js.el. >> They can *almost* be turned into `let' and `let*', except that >> (lexical-let ((buffer-file-name 3)) ...) will bind buffer-file-name >> lexically whereas `let' will always bind it dynamically. We could >> either ignore those issues or try to handle them, but I'd rather just >> mark lexical-let obsolete. > I'd prefer to ignore the issues for now and transform lexical-let to let > when lexical-binding is on, generating a compiler error if we're trying to > lexically bind a special variable. I don't think many people try to do > that. A macro that uses a lexical binding in its generated code still needs > to use lexical-let in order for its generated form to work properly in > either environment, and even outside macros, making lexical-let cheap in the > lexbound case gives us a way to create backward-compatible code that > automatically becomes more efficient in Emacs 24. I'd tend to agree, but see below. >> (Of course, there's also the difficulty for the macro to reliably >> determine whether the expansion will be run in lexical-binding or >> dynamic-binding mode). > Wouldn't inspecting the value of lexical-binding work well enough? Sadly, that is not reliable: it only indicates whether the code found in the current buffer uses lexical-binding, but the macro-call might be in a function defined in some other file/buffer. >>> - lexical-binding only applies to code evaluated by `eval-buffer' and >>> eval-region'?! So I can't make code evaluated by M-: lexbound? >> ?!? AFAIK, M-: uses lexical or dynamic scoping according to the value >> of lexical-binding in the current buffer. > It does, but the documentation string still gives me the impression that it > wouldn't be. What part of its docstring gives you this impression? > Why isn't lexical-binding respected for all evaluation? I tried to patch all places where it needs to be used. If I missed some, please point them out. >> Currently, I think the best way to do that is to add the feature to the >> byte-compiler. The most promising avenue for it might be to use code >> of the form ((closure ()<formalargs> <lexbindcode>)<actualargs>) and >> compile efficiently (I think currently such code will either result in >> a complaint about a malformed function, or else will leave the function >> uncompiled). > Ah, I see what you mean. Would a with-lexical-scope form suffice? > ;; with-lexical-scope is itself compiled with lexical-binding t > (defmacro* with-lexical-scope (&body body) > (let* ((vars (remove-if (lambda (var) > (or (special-variable-p var) > (not (boundp var)))) > (find-free-vars `(progn ,@body)))) > (closure `(closure (t) ; no environment > ,@args ,@body))) > `(funcall ,closure ,@vars))) I think I'd rather just do: (defmacro with-lexical-scope (&rest body) `((closure (t) () ,@body))) That avoids several problems: - no need to implement find-free-vars (tho it's already in cconv.el). - no need to macroexpand-all and traverse `body' to find its free vars. - `boundp' won't DTRT in the byte-compiler (you'd want to consult byte-compile-bound-variables instead). - the semantics of capturing dynbound variables as if they were lexical vars sounds nasty. - you copy the value of the free vars, which will only do the right thing if those vars aren't mutated. Of course, to make the above work, you still need to teach the byte-compiler how to handle such code, which shouldn't be too hard. >> IIRC, the reason why defun doesn't work for it is fundamentally linked >> to some silly technicality, but I justify it for myself by the fact that >> all the "defun within a non-empty context" I've seen were bogus, so I'm >> not strongly motivated to handle it right. > Even if it's not particularly common, being consistent with Common Lisp and > having fewer special cases are good things. Some people use constructs like > this to create module-private variables (which is a bad idea, but that > doesn't stop people doing it.) The right way to fix it is to make defun (and defmacro) a macro, and that would be a good thing it its own right. When I tried that the only problem I bumped into is that we want to dump "#$" in the .elc file to refer to load-file-name for on-demand-loading of docstrings, so as soon as someone comes up with a clean/neat way to get `pr in1' to output a "#$", we'll turn defun and defmacro into macros and this issue will disappear. >>> - Disassembling a closure reports closed-over variables as constants; >>> they're not. >> They are. > Err, yes. They are. Thank you ;-) >>> - Do we really use a whole cons cell for each closed-over variable, even in >>> compiled code? >> Yes, tho only for variables which are mutated (yup, `setq' is costly). > Couldn't we create a box type, which would would be like a cons except that > it'd hold just one value? (The #<foo> read-syntax is available.) What for? We currently use the lower 3 bits for tag, so objects have to be aligned on a multiple of 8, so on 32bit systems the smallest objects we can handle use up 64bits; and since in such systems cons cells use up 65bits, they're pretty close to optimal. Also cons cells have their tag in the immediate 3bit tag which is good for efficiency, but if we want to add another small object we wouldn't be able to use one of those 3bit tag values for it because they're all used already, so we'd have to treat it as a special kind of vector or misc type but all of those objects already need more than 64bits... nah, cons cells work just fine. OTOH we do need to reduce the number of cases where we have to convert variables to cons-cells, and that mostly means "use fewer closures". This is actually "easy" to do right now: change the (byte-code/compiler) implementation of condition-case, unwind-protect, and catch so they don't require closures, since they're the main source of closures. Stefan ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-29 21:44 lexbind ready for merge Stefan Monnier 2011-03-29 23:43 ` Daniel Colascione @ 2011-03-30 7:28 ` Tassilo Horn 2011-03-30 11:30 ` Eli Zaretskii 2011-03-30 14:29 ` Stefan Monnier 1 sibling, 2 replies; 33+ messages in thread From: Tassilo Horn @ 2011-03-30 7:28 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Stefan Monnier <monnier@IRO.UMontreal.CA> writes: > OK, so AFAIK the lexbind branch is pretty much ready for merge. The > only issue is that I'm not sure it has seen as much testing as I'd > like, but then that's largely because it hasn't been merged yet. So > if I don't hear any screams until then, I plan to merge it into trunk > over the week-end or nearby. Please go for it. I'm using it since about a week, and I didn't run on errors (that haven't been solved until now)... ...except that the current git version of Gnus doesn't build with lexbind emacs: --8<---------------cut here---------------start------------->8--- % make cd lisp && make EMACS="emacs" lispdir="/usr/share/emacs/site-lisp/gnus" all make[1]: Entering directory `/home/horn/repos/el/gnus/lisp' rm -f *.elc gnus-load.el auto-autoloads.* custom-load.* URLDIR="/usr/share/emacs/24.0.50/lisp/url/" W3DIR="no" lispdir="/usr/share/emacs/site-lisp/gnus" srcdir=. emacs -batch -q -no-site-file -l ./dgnushack.el -f dgnushack-make-cus-load . Debugger entered--Lisp error: (wrong-number-of-arguments (1 . 1) 2) byte-compile-from-buffer(#<buffer *temp*> "foo.el") (progn (insert "(defcustom foo (1+ (random)) \"\" :group 'emacs)\n") (byte-compile-from-buffer (current-buffer) "foo.el")) (unwind-protect (progn (insert "(defcustom foo (1+ (random)) \"\" :group 'emacs)\n") (byte-compile-from-buffer (current-buffer) "foo.el")) (and (buffer-name temp-buffer) (kill-buffer temp-buffer))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (insert "(defcustom foo (1+ (random)) \"\" :group 'emacs)\n") (byte-compile-from-buffer (current-buffer) "foo.el")) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))) (with-current-buffer temp-buffer (unwind-protect (progn (insert "(defcustom foo (1+ (random)) \"\" :group 'emacs)\n") (byte-compile-from-buffer (current-buffer) "foo.el")) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))) (let ((temp-buffer (generate-new-buffer " *temp*"))) (with-current-buffer temp-buffer (unwind-protect (progn (insert "(defcustom foo (1+ (random)) \"\" :group 'emacs)\n") (byte-compile-from-buffer (current-buffer) "foo.el")) (and (buffer-name temp-buffer) (kill-buffer temp-buffer))))) (with-temp-buffer (insert "(defcustom foo (1+ (random)) \"\" :group 'emacs)\n") (byte-compile-from-buffer (current-buffer) "foo.el")) (let ((outbuf (with-temp-buffer (insert "(defcustom foo (1+ (random)) \"\" :group 'emacs)\n") (byte-compile-from-buffer (current-buffer) "foo.el")))) (when outbuf (prog1 (with-current-buffer outbuf (goto-char (point-min)) (search-forward " 'foo '(byte-code " nil t)) (kill-buffer outbuf)))) dgnushack-emacs-compile-defcustom-p() (if (dgnushack-emacs-compile-defcustom-p) (progn (maybe-fbind (quote (defined-colors face-attribute))) (maybe-bind (quote (idna-program installation-directory))))) (when (dgnushack-emacs-compile-defcustom-p) (maybe-fbind (quote (defined-colors face-attribute))) (maybe-bind (quote (idna-program installation-directory)))) eval-buffer(#<buffer *load*> nil "/home/horn/repos/el/gnus/lisp/dgnushack.el" nil t) ; Reading at buffer position 9629 load-with-code-conversion("/home/horn/repos/el/gnus/lisp/dgnushack.el" "/home/horn/repos/el/gnus/lisp/dgnushack.el" nil t) load("/home/horn/repos/el/gnus/lisp/dgnushack.el" nil t) command-line-1(("-l" "./dgnushack.el" "-f" "dgnushack-make-cus-load" ".")) command-line() normal-top-level() make[1]: *** [gnus-load.el] Error 255 make[1]: Leaving directory `/home/horn/repos/el/gnus/lisp' make: *** [lick] Error 2 --8<---------------cut here---------------end--------------->8--- The reason is that in trunk, that function has the signature byte-compile-from-buffer (bytecomp-inbuffer &optional bytecomp-filename) but in the lexbind branch, the optional bytecomp-filename has been removed: byte-compile-from-buffer (inbuffer) AFAIKS, gnus doesn't use the foo.el file anyway, so basically that arg can be removed. But maybe the `byte-compile-from-buffer' definition in [[S]X]Emacs requires exactly 2 arguments? I don't know... Bye, Tassilo ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 7:28 ` Tassilo Horn @ 2011-03-30 11:30 ` Eli Zaretskii 2011-03-30 13:10 ` Tassilo Horn 2011-03-30 13:17 ` Ted Zlatanov 2011-03-30 14:29 ` Stefan Monnier 1 sibling, 2 replies; 33+ messages in thread From: Eli Zaretskii @ 2011-03-30 11:30 UTC (permalink / raw) To: Tassilo Horn; +Cc: monnier, emacs-devel > From: Tassilo Horn <tassilo@member.fsf.org> > Date: Wed, 30 Mar 2011 09:28:57 +0200 > Cc: emacs-devel@gnu.org > > Please go for it. > [...] > ...except that the current git version of Gnus doesn't build with > lexbind emacs: So how is it a good idea to "go for it"? Gnus is resync'ed with Emacs practically every day, so chances are they will resync before Stefan gets around to merging the branch. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 11:30 ` Eli Zaretskii @ 2011-03-30 13:10 ` Tassilo Horn 2011-03-30 13:17 ` Ted Zlatanov 1 sibling, 0 replies; 33+ messages in thread From: Tassilo Horn @ 2011-03-30 13:10 UTC (permalink / raw) To: Eli Zaretskii; +Cc: monnier, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: Hi Eli, >> Please go for it. >> [...] >> ...except that the current git version of Gnus doesn't build with >> lexbind emacs: > > So how is it a good idea to "go for it"? Gnus is resync'ed with Emacs > practically every day, so chances are they will resync before Stefan > gets around to merging the branch. The problematic file dgnushack.el is not included in emacs. It's only used by the standalone gnus version. I've already reported the issue at the Gnus mailinglist, so I'm pretty confident that it will be taken care of even before the weekend. Bye, Tassilo ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 11:30 ` Eli Zaretskii 2011-03-30 13:10 ` Tassilo Horn @ 2011-03-30 13:17 ` Ted Zlatanov 1 sibling, 0 replies; 33+ messages in thread From: Ted Zlatanov @ 2011-03-30 13:17 UTC (permalink / raw) To: emacs-devel On Wed, 30 Mar 2011 07:30:53 -0400 Eli Zaretskii <eliz@gnu.org> wrote: >> From: Tassilo Horn <tassilo@member.fsf.org> >> Date: Wed, 30 Mar 2011 09:28:57 +0200 >> Cc: emacs-devel@gnu.org >> >> Please go for it. >> [...] >> ...except that the current git version of Gnus doesn't build with >> lexbind emacs: EZ> So how is it a good idea to "go for it"? Gnus is resync'ed with Emacs EZ> practically every day, so chances are they will resync before Stefan EZ> gets around to merging the branch. Gnus is synchronized with Emacs manually by Katsumi Yamaoka. He can abstain from running the sync if Stefan or someone else asks. Ted ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 7:28 ` Tassilo Horn 2011-03-30 11:30 ` Eli Zaretskii @ 2011-03-30 14:29 ` Stefan Monnier 2011-03-30 14:54 ` Tassilo Horn 2011-03-30 16:11 ` Lars Magne Ingebrigtsen 1 sibling, 2 replies; 33+ messages in thread From: Stefan Monnier @ 2011-03-30 14:29 UTC (permalink / raw) To: Tassilo Horn; +Cc: emacs-devel > The reason is that in trunk, that function has the signature > byte-compile-from-buffer (bytecomp-inbuffer &optional bytecomp-filename) > but in the lexbind branch, the optional bytecomp-filename has been > removed: > byte-compile-from-buffer (inbuffer) > AFAIKS, gnus doesn't use the foo.el file anyway, so basically that arg > can be removed. But maybe the `byte-compile-from-buffer' definition in > [[S]X]Emacs requires exactly 2 arguments? I don't know... Why on earth does Gnus need to call byte-compile-from-buffer? Stefan ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 14:29 ` Stefan Monnier @ 2011-03-30 14:54 ` Tassilo Horn 2011-03-31 1:02 ` Stephen J. Turnbull 2011-03-30 16:11 ` Lars Magne Ingebrigtsen 1 sibling, 1 reply; 33+ messages in thread From: Tassilo Horn @ 2011-03-30 14:54 UTC (permalink / raw) To: Stefan Monnier; +Cc: ding, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> The reason is that in trunk, that function has the signature >> byte-compile-from-buffer (bytecomp-inbuffer &optional bytecomp-filename) >> but in the lexbind branch, the optional bytecomp-filename has been >> removed: > >> byte-compile-from-buffer (inbuffer) > >> AFAIKS, gnus doesn't use the foo.el file anyway, so basically that arg >> can be removed. But maybe the `byte-compile-from-buffer' definition in >> [[S]X]Emacs requires exactly 2 arguments? I don't know... > > Why on earth does Gnus need to call byte-compile-from-buffer? The purpose of the whole dgnushack.el is to figure out the correct load-path when byte-compiling. But I'm the wrong person to ask why that messy dance has to be danced... I added the Gnus list to the Cc. The function definition is (defun dgnushack-emacs-compile-defcustom-p () "Return non-nil if Emacs byte compiles `defcustom' forms. Those Emacsen will warn against undefined variables and functions used in `defcustom' forms." (let ((outbuf (with-temp-buffer (insert "(defcustom foo (1+ (random)) \"\" :group 'emacs)\n") (byte-compile-from-buffer (current-buffer) "foo.el")))) (when outbuf (prog1 (with-current-buffer outbuf (goto-char (point-min)) (search-forward " 'foo '(byte-code " nil t)) (kill-buffer outbuf))))) and its use is in dgnushack's form (when (dgnushack-emacs-compile-defcustom-p) (maybe-fbind '(defined-colors face-attribute)) (maybe-bind '(idna-program installation-directory))) where maybe-[f]bind is declared in lpath.el, whose top level comment is ;; Shut up. ;-) Bye, Tassilo ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 14:54 ` Tassilo Horn @ 2011-03-31 1:02 ` Stephen J. Turnbull 0 siblings, 0 replies; 33+ messages in thread From: Stephen J. Turnbull @ 2011-03-31 1:02 UTC (permalink / raw) To: Tassilo Horn; +Cc: Stefan Monnier, ding, emacs-devel Tassilo Horn writes: > >> AFAIKS, gnus doesn't use the foo.el file anyway, so basically that arg > >> can be removed. But maybe the `byte-compile-from-buffer' definition in > >> [[S]X]Emacs requires exactly 2 arguments? I don't know... (defun byte-compile-from-buffer (byte-compile-inbuffer filename &optional eval) ;; buffer --> output-buffer, or buffer --> eval form, return nil I don't know why FILENAME is not optional in XEmacs; it can be nil. It can be used in non-trivial ways in that function. Among others, it is used in an error message, which would be confusing if the value were nil. For that reason, I personally would tend to oppose changing the signature, to remind callers that null FILENAME is not without drawbacks. It's not clear to me what the semantics of the other uses of FILENAME are, but since it's explicitly tested as a boolean at least once, XEmacs is apparently prepared for it to be nil. > > Why on earth does Gnus need to call byte-compile-from-buffer? "The Gnus that is the true Gnus calls byte-compiler-from-buffer. Otherwise it would not be Gnus." -- larsi-tse, "Gnus Te Ching" <wink /> ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 14:29 ` Stefan Monnier 2011-03-30 14:54 ` Tassilo Horn @ 2011-03-30 16:11 ` Lars Magne Ingebrigtsen 2011-03-30 17:10 ` Tassilo Horn 1 sibling, 1 reply; 33+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-03-30 16:11 UTC (permalink / raw) To: emacs-devel; +Cc: ding Stefan Monnier <monnier@iro.umontreal.ca> writes: > Why on earth does Gnus need to call byte-compile-from-buffer? It seems to be code dealing with something on XEmacs introduced in 2007. I've now disabled the code when running under Emacs. -- (domestic pets only, the antidote for overdose, milk.) larsi@gnus.org * Lars Magne Ingebrigtsen ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: lexbind ready for merge 2011-03-30 16:11 ` Lars Magne Ingebrigtsen @ 2011-03-30 17:10 ` Tassilo Horn 0 siblings, 0 replies; 33+ messages in thread From: Tassilo Horn @ 2011-03-30 17:10 UTC (permalink / raw) To: emacs-devel Lars Magne Ingebrigtsen <larsi@gnus.org> writes: > Stefan Monnier <monnier@iro.umontreal.ca> writes: > >> Why on earth does Gnus need to call byte-compile-from-buffer? > > It seems to be code dealing with something on XEmacs introduced in > 2007. I've now disabled the code when running under Emacs. Yup, I can confirm that git Gnus builds fine with lexbind emacs now. Bye, Tassilo ^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2011-04-01 21:25 UTC | newest] Thread overview: 33+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-03-29 21:44 lexbind ready for merge Stefan Monnier 2011-03-29 23:43 ` Daniel Colascione 2011-03-30 1:22 ` Stefan Monnier 2011-03-30 4:10 ` Daniel Colascione 2011-03-30 11:35 ` Juanma Barranquero 2011-03-30 13:24 ` lexbind: how to replace lexical-let approach to hide secrets (was: lexbind ready for merge) Ted Zlatanov 2011-03-30 21:12 ` lexbind: how to replace lexical-let approach to hide secrets Stefan Monnier 2011-03-30 21:56 ` David Kastrup 2011-03-30 22:29 ` Daniel Colascione 2011-03-31 15:42 ` Ted Zlatanov 2011-04-01 1:31 ` Stephen J. Turnbull 2011-04-01 4:41 ` secret strings (was: lexbind: how to replace lexical-let approach to hide secrets) Ted Zlatanov 2011-04-01 5:52 ` Stephen J. Turnbull 2011-04-01 11:02 ` secret strings Ted Zlatanov 2011-04-01 14:38 ` Stephen J. Turnbull 2011-04-01 15:12 ` Ted Zlatanov 2011-04-01 16:14 ` Stephen J. Turnbull 2011-04-01 20:08 ` Ted Zlatanov 2011-04-01 20:34 ` Stefan Monnier 2011-04-01 21:25 ` Ted Zlatanov 2011-04-01 14:59 ` Stefan Monnier 2011-03-30 15:09 ` lexbind ready for merge Daniel Colascione 2011-03-30 15:20 ` Juanma Barranquero 2011-03-30 14:26 ` Stefan Monnier 2011-03-30 7:28 ` Tassilo Horn 2011-03-30 11:30 ` Eli Zaretskii 2011-03-30 13:10 ` Tassilo Horn 2011-03-30 13:17 ` Ted Zlatanov 2011-03-30 14:29 ` Stefan Monnier 2011-03-30 14:54 ` Tassilo Horn 2011-03-31 1:02 ` Stephen J. Turnbull 2011-03-30 16:11 ` Lars Magne Ingebrigtsen 2011-03-30 17:10 ` Tassilo Horn
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).