Fix security flaw in EDE, bug 398227. Update ebuild to EAPI 4.
authorUlrich Müller <ulm@gentoo.org>
Mon, 9 Jan 2012 11:09:29 +0000 (11:09 +0000)
committerUlrich Müller <ulm@gentoo.org>
Mon, 9 Jan 2012 11:09:29 +0000 (11:09 +0000)
Package-Manager: portage-2.1.10.44/cvs/Linux x86_64

app-emacs/cedet/ChangeLog
app-emacs/cedet/Manifest
app-emacs/cedet/cedet-1.0-r1.ebuild [new file with mode: 0644]
app-emacs/cedet/files/cedet-1.0-ede_security_fix.patch [new file with mode: 0644]

index d133d3d4b57c043bd81cb4baf311fabe9cbbf043..029e35e387835412dcbfaadceaa5e43cc1758cdd 100644 (file)
@@ -1,6 +1,12 @@
 # ChangeLog for app-emacs/cedet
-# Copyright 1999-2011 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/app-emacs/cedet/ChangeLog,v 1.63 2011/01/25 18:02:00 ulm Exp $
+# Copyright 1999-2012 Gentoo Foundation; Distributed under the GPL v2
+# $Header: /var/cvsroot/gentoo-x86/app-emacs/cedet/ChangeLog,v 1.64 2012/01/09 11:09:29 ulm Exp $
+
+*cedet-1.0-r1 (09 Jan 2012)
+
+  09 Jan 2012; Ulrich Müller <ulm@gentoo.org> +cedet-1.0-r1.ebuild,
+  +files/cedet-1.0-ede_security_fix.patch:
+  Fix security flaw in EDE, bug 398227. Update ebuild to EAPI 4.
 
   25 Jan 2011; Ulrich Mueller <ulm@gentoo.org> cedet-1.0.ebuild:
   Supply subdirectories of S in load-path, bug 349790.
index 33f93345b9c6670528d30a563ca9829a78cd8da7..a14ac70e16922b75ab8aab01b79ca6b4f4f682a6 100644 (file)
@@ -2,14 +2,26 @@
 Hash: SHA1
 
 AUX 50cedet-gentoo.el 556 RMD160 b7f5cb7631c0eb1bdea6cfa7e320fb127f9769d6 SHA1 e5dcd163996d7a3c3e8eaf74f7ce6d10da8ba2b8 SHA256 a6fb7de601604f95bfd5800ebf01a599debb848d3dfdc21b74eb22869a1627e1
+AUX cedet-1.0-ede_security_fix.patch 14103 RMD160 3f4e255efa4e9f488d2d19b9d3d8a1953bedbe93 SHA1 83d91d36777052580e3dce56c235c1a9cd3d379f SHA256 89f44aaa6297f820b2f4efb4dfca91398e3d4f4a6a89174d32992f0cfd286186
 DIST cedet-1.0.tar.gz 2100938 RMD160 a3703cb76f21468a1d218a091599441ca9aa5d11 SHA1 bc3c7c22465f79df603fb6bb5684442a439f198e SHA256 f0d5c76d22a8d7dceaccb659be094c44cb999eae75db3545eef086d8dcd342f4
+EBUILD cedet-1.0-r1.ebuild 2289 RMD160 ed31576d2ea82fe4d10ff64cf34260a001bb5d94 SHA1 2f3efa6e038ea87910a5bc18d96dd1db8bc0f542 SHA256 b525285d8b61061a8b1c09e121c13fb738d1e2fd676153e74bd7224f4c1d03f0
 EBUILD cedet-1.0.ebuild 2399 RMD160 eaaea9a673ca2d0bc4cbbecae753f6cba670d0d8 SHA1 506829ace408f773e86b629d881c03967a15fd95 SHA256 c632436c8c2f210200f3b26b052becdab94154c7f5134efa1f69f50654d8c7cf
-MISC ChangeLog 8945 RMD160 8db7cf0d3bac0dcb6448ccfd84546dcf5e6855ca SHA1 d6c468766339cec0a815f504e6e1ff592550bcd5 SHA256 2c8ae7ad0a1c85b9bbd00db9c86b1be68de75145dc7397642bec25b7ebc73ade
+MISC ChangeLog 9152 RMD160 8feb195778c042b9767da9f4cc846019d69efd57 SHA1 b762b9cc148eea4ee67163000800791a2c78865a SHA256 d4f3ed93a0d00456fb7b691746e3e95fe5dadb105f19719259f290eb2d082228
 MISC metadata.xml 831 RMD160 742d588c9f37c4639acf627470e88e8da5c9e8c4 SHA1 315ec457e01f99f17211cf7229a17caec0ff3bf6 SHA256 3ef03457bb7af19d84fdd463e7a780ee79fa2812f5bd04fe5b15064d648b2999
 -----BEGIN PGP SIGNATURE-----
-Version: GnuPG v2.0.17 (GNU/Linux)
+Version: GnuPG v2.0.18 (GNU/Linux)
 
-iEYEARECAAYFAk0/EV4ACgkQOeoy/oIi7ux1yACfVDzVy4zv8EzvJjPUvfXTyXAs
-ySoAoLJxo+uFJi0dVdEL+EHZojnUlxgy
-=uIly
+iQIcBAEBAgAGBQJPCsrzAAoJEDxpGckxwJCBwkAP/jH9G2jirkL4YLhQLMJqA6Hu
+ZydRtWPt1sZli/XP3yQJzs57ZGpkE3MBd3t37ClgoPSB5vmmk0TnACPdunPTaQv6
+yJB2cpoaL10cxi6GLbTkbzdPBMg0wqyJm8d2P3NFnQt3/5XQtNN0e2d8Xsfz9UUU
+4rop1Zg9uMGAVUSU98sNTYdX5IlEYbe2BvRhKNDft+Dsqb+MD91nt9sQ1v/Zv0mC
+P4eFY8QKRrpfcEEidlXUgDrgcSjSkxfklBdskaxmtQuoofNBaRB21doZIg8fFtPJ
+a99QpOo5wl40Itxc/VpOE5b7xQtNwocL/DYV5OFRmILGRq29f7pgHx1sgbL/cfQu
+M20WH3v+3mg5EUtMMOAP6gKzAUGs++Nxw0OCK2frxmCav+vEIV1Y037IGG3WMi5v
+xNHgSrOqpQhZIUOm2zfQhuX5pKVEst9ZX/URfaVQlBz7714P67FYzlvQhGl5Vx1B
+isNpuCxs2Ed3aWfpuYV1rOkBqWs8pKLR5KdI4OVP/PRGG2zx5O12rYbhg8+pwx5W
+M471GasRg7LcvplH+v0KJLLR5m33Vp/AGWoQrxF3i501JM9FPUcsde05KXGTC4gw
+BomjoOqqWeJa6SA0fLKaNN488/YlR9C+QVTYwgtAAZ2r1JhmzZNQpiIOgVrY3Xnu
+hXED32vbrCvLtzNDpEvr
+=cZ9n
 -----END PGP SIGNATURE-----
diff --git a/app-emacs/cedet/cedet-1.0-r1.ebuild b/app-emacs/cedet/cedet-1.0-r1.ebuild
new file mode 100644 (file)
index 0000000..2fa3e54
--- /dev/null
@@ -0,0 +1,80 @@
+# Copyright 1999-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/app-emacs/cedet/cedet-1.0-r1.ebuild,v 1.1 2012/01/09 11:09:29 ulm Exp $
+
+EAPI=4
+NEED_EMACS=22
+
+inherit elisp
+
+MY_P=${P/_}
+DESCRIPTION="CEDET: Collection of Emacs Development Environment Tools"
+HOMEPAGE="http://cedet.sourceforge.net/"
+SRC_URI="mirror://sourceforge/cedet/${MY_P}.tar.gz"
+
+LICENSE="GPL-2 FDL-1.2"
+SLOT="0"
+KEYWORDS="~amd64 ~ppc ~sparc ~x86 ~amd64-linux ~x86-linux ~x86-macos ~sparc-solaris"
+IUSE=""
+
+S="${WORKDIR}/${MY_P}"
+ELISP_PATCHES="${P}-ede_security_fix.patch"
+SITEFILE="50${PN}-gentoo.el"
+EMACSFLAGS="${EMACSFLAGS} -L ${S}/eieio -L ${S}/semantic -L ${S}/srecode \
+       -L ${S}/ede -L ${S}/speedbar -L ${S}/cogre"
+
+src_compile() {
+       emake -j1 \
+               EMACS="${EMACS}" \
+               EMACSFLAGS="${EMACSFLAGS}"
+}
+
+src_test() {
+       emake -j1 \
+               EMACS="${EMACS}" \
+               EMACSFLAGS="${EMACSFLAGS}" \
+               utest
+}
+
+src_install() {
+       local target file dir
+       find . -type d -name tests -prune -o -type f -print | while read target
+       do
+               file=${target##*/}
+               dir=${target%/*}; dir=${dir#./}
+               case "${file}" in
+                       *~ | Makefile | *.texi | *-script | PRERELEASE_CHECKLIST \
+                               | Project.ede | USING_CEDET_FROM_CVS | grammar-fw-ov.txt)
+                               ;;
+                       ChangeLog | README | AUTHORS | *NEWS | INSTALL \
+                               | renamelist.txt | semanticdb.sh)
+                               docinto "${dir}"
+                               dodoc "${target}" ;;
+                       *.el | *.by | *.wy)
+                               # install grammar sources along with the elisp files, since
+                               # the location where semantic expects them is not configurable
+                               insinto "${SITELISP}/${PN}/${dir}"
+                               doins "${target}" ;;
+                       *.elc)
+                               # we are in a subshell, so collecting in a variable won't work
+                               echo "${target}" >>"${T}/elc-list.txt" ;;
+                       *.srt | *.xpm)
+                               insinto "${SITEETC}/${PN}/${dir}"
+                               doins "${target}" ;;
+                       *.info* | grammar-fw-ov.png)
+                               doinfo "${target}" ;;
+                       *)
+                               die "Unrecognised file ${target}" ;;
+               esac
+       done
+
+       # make sure that the compiled elisp files have a later time stamp than
+       # the corresponding sources, in order to suppress warnings at run time
+       while read target; do
+               dir=${target%/*}; dir=${dir#./}
+               insinto "${SITELISP}/${PN}/${dir}"
+               doins "${target}"
+       done <"${T}/elc-list.txt"
+
+       elisp-site-file-install "${FILESDIR}/${SITEFILE}" || die
+}
diff --git a/app-emacs/cedet/files/cedet-1.0-ede_security_fix.patch b/app-emacs/cedet/files/cedet-1.0-ede_security_fix.patch
new file mode 100644 (file)
index 0000000..8bf5632
--- /dev/null
@@ -0,0 +1,379 @@
+http://lists.gnu.org/archive/html/emacs-devel/2012-01/msg00387.html
+https://bugs.gentoo.org/398227
+
+--- cedet-1.0-orig/ede/ede-auto.el
++++ cedet-1.0/ede/ede-auto.el
+@@ -57,6 +57,13 @@
+         :initform t
+         :documentation
+         "Non-nil if this is an option when a user creates a project.")
++   (safe-p :initarg :safe-p
++         :initform t
++         :documentation
++         "Non-nil if the project load files are \"safe\".
++An unsafe project is one that loads project variables via Emacs
++Lisp code.  A safe project is one that loads project variables by
++scanning files without loading Lisp code from them.")
+    )
+   "Class representing minimal knowledge set to run preliminary EDE functions.
+ When more advanced functionality is needed from a project type, that projects
+@@ -68,13 +75,15 @@
+                        :name "Make" :file 'ede-proj
+                        :proj-file "Project.ede"
+                        :load-type 'ede-proj-load
+-                       :class-sym 'ede-proj-project)
++                       :class-sym 'ede-proj-project
++                       :safe-p nil)
+    (ede-project-autoload "edeproject-automake"
+                        :name "Automake" :file 'ede-proj
+                        :proj-file "Project.ede"
+                        :initializers '(:makefile-type Makefile.am)
+                        :load-type 'ede-proj-load
+-                       :class-sym 'ede-proj-project)
++                       :class-sym 'ede-proj-project
++                       :safe-p nil)
+    (ede-project-autoload "automake"
+                        :name "automake" :file 'project-am
+                        :proj-file "Makefile.am"
+@@ -84,6 +93,8 @@
+    )
+   "List of vectors defining how to determine what type of projects exist.")
++(put 'ede-project-class-files 'risky-local-variable t)
++
+ ;;; EDE project-autoload methods
+ ;;
+ (defmethod ede-project-root ((this ede-project-autoload))
+@@ -122,6 +133,19 @@
+     (when (and f (file-exists-p f))
+       f)))
++(defmethod ede-auto-load-project ((this ede-project-autoload) dir)
++  "Load in the project associated with THIS project autoload description.
++THIS project description should be valid for DIR, where the project will
++be loaded."
++  ;; Last line of defense: don't load unsafe projects.
++  (when (not (or (oref this :safe-p)
++               (ede-directory-safe-p dir)))
++    (error "Attempt to load an unsafe project (bug elsewhere in EDE)"))
++  ;; Things are good - so load the project.
++  (let ((o (funcall (oref this load-type) dir)))
++    (when (not o)
++      (error "Project type error: :load-type failed to create a project"))
++    (ede-add-project-to-global-list o)))
+ (provide 'ede-auto)
+--- cedet-1.0-orig/ede/ede-simple.el
++++ cedet-1.0/ede/ede-simple.el
+@@ -51,7 +51,8 @@
+             :name "Simple" :file 'ede-simple
+             :proj-file 'ede-simple-projectfile-for-dir
+             :load-type 'ede-simple-load
+-            :class-sym 'ede-simple-project)
++            :class-sym 'ede-simple-project
++            :safe-p nil)
+            t)
+ (defcustom ede-simple-save-directory "~/.ede"
+--- cedet-1.0-orig/ede/ede.el
++++ cedet-1.0/ede/ede.el
+@@ -81,6 +81,42 @@
+ (require 'ede-auto)
+ (require 'ede-base)
++(defcustom ede-project-directories nil
++  "Directories in which EDE may search for project files.
++If the value is t, EDE may search in any directory.
++
++If the value is a function, EDE calls that function with one
++argument, the directory name; the function should return t iff
++EDE should look for project files in the directory.
++
++Otherwise, the value should be a list of fully-expanded directory
++names.  EDE searches for project files only in those directories.
++If you invoke the commands \\[ede] or \\[ede-new] on a directory
++that is not listed, Emacs will offer to add it to the list.
++
++Any other value disables searching for EDE project files."
++  :group 'ede
++  :type '(choice (const :tag "Any directory" t)
++               (repeat :tag "List of directories"
++                       (directory))
++               (function :tag "Predicate"))
++  :version "23.4"
++  :risky t)
++
++(defun ede-directory-safe-p (dir)
++  "Return non-nil if DIR is a safe directory to load projects from.
++Projects that do not load a project definition as Emacs Lisp code
++are safe, and can be loaded automatically.  Other project types,
++such as those created with Project.ede files, are safe only if
++specified by `ede-project-directories'."
++  (setq dir (directory-file-name (expand-file-name dir)))
++  ;; Load only if allowed by `ede-project-directories'.
++  (or (eq ede-project-directories t)
++      (and (functionp ede-project-directories)
++         (funcall ede-project-directories dir))
++      (and (listp ede-project-directories)
++         (member dir ede-project-directories))))
++
\f
+ ;;; Management variables
+ ;;
+@@ -408,24 +444,42 @@
+ Sets buffer local variables for EDE."
+   (let* ((ROOT nil)
+        (proj (ede-directory-get-open-project default-directory
+-                                             'ROOT)))
++                                             'ROOT))
++       (projauto nil))
++
+     (when (or proj ROOT
+-            (ede-directory-project-p default-directory t))
++            ;; If there is no open project, look up the project
++            ;; autoloader to see if we should initialize.
++            (setq projauto (ede-directory-project-p default-directory t)))
++
++      (when (and (not proj) projauto)
++
++      ;; No project was loaded, but we have a project description
++      ;; object.  This means that we can check if it is a safe
++      ;; project to load before requesting it to be loaded.
++
++      (when (or (oref projauto safe-p)
++                ;; The project style is not safe, so check if it is
++                ;; in `ede-project-directories'.
++                (let ((top (ede-toplevel-project default-directory)))
++                  (ede-directory-safe-p top)))
++
++        ;; The project is safe, so load it in.
++        (setq proj (ede-load-project-file default-directory 'ROOT))))
+-      (when (not proj)
+-      ;; @todo - this could be wasteful.
+-      (setq proj (ede-load-project-file default-directory 'ROOT)))
++      ;; Only initialize EDE state in this buffer if we found a project.
++      (when proj
+-      (setq ede-object (ede-buffer-object (current-buffer)
++      (setq ede-object (ede-buffer-object (current-buffer)
+                                         'ede-object-project))
+-      (setq ede-object-root-project
+-          (or ROOT (ede-project-root ede-object-project)))
++      (setq ede-object-root-project
++            (or ROOT (ede-project-root ede-object-project)))
+-      (if (and (not ede-object) ede-object-project)
+-        (ede-auto-add-to-target))
++      (if (and (not ede-object) ede-object-project)
++          (ede-auto-add-to-target))
+-      (ede-apply-target-options))))
++      (ede-apply-target-options)))))
+ (defun ede-reset-all-buffers (onoff)
+   "Reset all the buffers due to change in EDE.
+@@ -534,13 +588,73 @@
\f
+ ;;; Interactive method invocations
+ ;;
+-(defun ede (file)
+-  "Start up EDE on something.
+-Argument FILE is the file or directory to load a project from."
+-  (interactive "fProject File: ")
+-  (if (not (file-exists-p file))
+-      (ede-new file)
+-    (ede-load-project-file (file-name-directory file))))
++(defun ede (dir)
++  "Start up EDE for directory DIR.
++If DIR has an existing project file, load it.
++Otherwise, create a new project for DIR."
++  (interactive
++   ;; When choosing a directory to turn on, and we see some directory here,
++   ;; provide that as the default.
++   (let* ((top (ede-toplevel-project default-directory))
++        (promptdflt (or top default-directory)))
++     (list (read-directory-name "Project directory: "
++                              promptdflt promptdflt t))))
++  (unless (file-directory-p dir)
++    (error "%s is not a directory" dir))
++  (when (ede-directory-get-open-project dir)
++    (error "%s already has an open project associated with it" dir))
++
++  ;; Check if the directory has been added to the list of safe
++  ;; directories.  It can also add the directory to the safe list if
++  ;; the user chooses.
++  (if (ede-check-project-directory dir)
++      (progn
++      ;; If there is a project in DIR, load it, otherwise do
++      ;; nothing.
++      (ede-load-project-file dir)
++
++      ;; Check if we loaded anything on the previous line.
++      (if (ede-current-project dir)
++
++          ;; We successfully opened an existing project.  Some open
++          ;; buffers may also be referring to this project.
++          ;; Resetting all the buffers will get them to also point
++          ;; at this new open project.
++          (ede-reset-all-buffers 1)
++
++        ;; ELSE
++        ;; There was no project, so switch to `ede-new' which is how
++        ;; a user can select a new kind of project to create.
++        (let ((default-directory (expand-file-name dir)))
++          (call-interactively 'ede-new))))
++
++    ;; If the proposed directory isn't safe, then say so.
++    (error "%s is not an allowed project directory in `ede-project-directories'"
++         dir)))
++
++(defun ede-check-project-directory (dir)
++  "Check if DIR should be in `ede-project-directories'.
++If it is not, try asking the user if it should be added; if so,
++add it and save `ede-project-directories' via Customize.
++Return nil iff DIR should not be in `ede-project-directories'."
++  (setq dir (directory-file-name (expand-file-name dir))) ; strip trailing /
++  (or (eq ede-project-directories t)
++      (and (functionp ede-project-directories)
++         (funcall ede-project-directories dir))
++      ;; If `ede-project-directories' is a list, maybe add it.
++      (when (listp ede-project-directories)
++      (or (member dir ede-project-directories)
++          (when (y-or-n-p (format "`%s' is not listed in `ede-project-directories'.
++Add it to the list of allowed project directories? "
++                                  dir))
++            (push dir ede-project-directories)
++            ;; If possible, save `ede-project-directories'.
++            (if (or custom-file user-init-file)
++                (let ((coding-system-for-read nil))
++                  (customize-save-variable
++                   'ede-project-directories
++                   ede-project-directories)))
++            t)))))
+ (defun ede-new (type &optional name)
+   "Create a new project starting of project type TYPE.
+@@ -574,6 +688,11 @@
+     (error "Cannot create project in non-existent directory %s" default-directory))
+   (when (not (file-writable-p default-directory))
+     (error "No write permissions for %s" default-directory))
++  (unless (ede-check-project-directory default-directory)
++    (error "%s is not an allowed project directory in `ede-project-directories'"
++         default-directory))
++  ;; Make sure the project directory is loadable in the future.
++  (ede-check-project-directory default-directory)
+   ;; Create the project
+   (let* ((obj (object-assoc type 'name ede-project-class-files))
+        (nobj (let ((f (oref obj file))
+@@ -607,6 +726,10 @@
+       (ede-add-subproject pp nobj)
+       (ede-commit-project pp)))
+     (ede-commit-project nobj))
++  ;; Once the project is created, load it again.  This used to happen
++  ;; lazily, but with project loading occurring less often and with
++  ;; security in mind, this is now the safe time to reload.
++  (ede-load-project-file default-directory)
+   ;; Have the menu appear
+   (setq ede-minor-mode t)
+   ;; Allert the user
+@@ -629,11 +752,16 @@
+ (defun ede-rescan-toplevel ()
+   "Rescan all project files."
+   (interactive)
+-  (let ((toppath (ede-toplevel-project default-directory))
+-      (ede-deep-rescan t))
+-    (project-rescan (ede-load-project-file toppath))
+-    (ede-reset-all-buffers 1)
+-    ))
++  (if (not (ede-directory-get-open-project default-directory))
++      ;; This directory isn't open.  Can't rescan.
++      (error "Attempt to rescan a project that isn't open")
++
++    ;; Continue
++    (let ((toppath (ede-toplevel-project default-directory))
++        (ede-deep-rescan t))
++
++      (project-rescan (ede-load-project-file toppath))
++      (ede-reset-all-buffers 1))))
+ (defun ede-new-target (&rest args)
+   "Create a new target specific to this type of project file.
+@@ -877,7 +1005,7 @@
+   ;; Do the load
+   ;;(message "EDE LOAD : %S" file)
+   (let* ((file dir)
+-       (path (expand-file-name (file-name-directory file)))
++       (path (file-name-as-directory (expand-file-name dir)))
+        (pfc (ede-directory-project-p path))
+        (toppath nil)
+        (o nil))
+@@ -906,13 +1034,11 @@
+       ;; See if its been loaded before
+       (setq o (object-assoc (ede-dir-to-projectfile pfc toppath) 'file
+                           ede-projects))
+-      (if (not o)
+-        ;; If not, get it now.
+-        (let ((ede-constructing pfc))
+-          (setq o (funcall (oref pfc load-type) toppath))
+-          (when (not o)
+-            (error "Project type error: :load-type failed to create a project"))
+-          (ede-add-project-to-global-list o)))
++
++      ;; If not open yet, load it.
++      (unless o
++      (let ((ede-constructing pfc))
++        (setq o (ede-auto-load-project pfc toppath))))
+       ;; Return the found root project.
+       (when rootreturn (set rootreturn o))
+@@ -967,13 +1093,7 @@
+            (and root
+                 (ede-find-subproject-for-directory root updir))
+            ;; Try the all structure based search.
+-           (ede-directory-get-open-project updir)
+-           ;; Load up the project file as a last resort.
+-           ;; Last resort since it uses file-truename, and other
+-           ;; slow features.
+-           (and (ede-directory-project-p updir)
+-                (ede-load-project-file
+-                 (file-name-as-directory updir))))))))))
++           (ede-directory-get-open-project updir))))))))
+ (defun ede-current-project (&optional dir)
+   "Return the current project file.
+@@ -987,11 +1107,7 @@
+     ;; No current project.
+     (when (not ans)
+       (let* ((ldir (or dir default-directory)))
+-      (setq ans (ede-directory-get-open-project ldir))
+-      (or ans
+-          ;; No open project, if this dir pass project-p, then load.
+-          (when (ede-directory-project-p ldir)
+-            (setq ans (ede-load-project-file ldir))))))
++      (setq ans (ede-directory-get-open-project ldir))))
+     ;; Return what we found.
+     ans))
+@@ -1047,12 +1163,13 @@
+   "Return the project which is the parent of TARGET.
+ It is recommended you track the project a different way as this function
+ could become slow in time."
+-  ;; @todo - use ede-object-project as a starting point.
+-  (let ((ans nil) (projs ede-projects))
+-    (while (and (not ans) projs)
+-      (setq ans (ede-target-in-project-p (car projs) target)
+-          projs (cdr projs)))
+-    ans))
++  (or ede-object-project
++      ;; If not cached, derive it from the current directory of the target.
++      (let ((ans nil) (projs ede-projects))
++      (while (and (not ans) projs)
++        (setq ans (ede-target-in-project-p (car projs) target)
++              projs (cdr projs)))
++      ans)))
+ (defmethod ede-find-target ((proj ede-project) buffer)
+   "Fetch the target in PROJ belonging to BUFFER or nil."