Clojure

proxy-super does not restore original binding if call throws exception

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: Release 1.1, Release 1.2, Release 1.3, Release 1.5
  • Fix Version/s: Release 1.6
  • Component/s: None
  • Labels:
  • Patch:
    Code and Test
  • Approval:
    Ok

Description

The code for proxy-call-with-super internally used by proxy-super does not handle exceptions from the call method:

(defn proxy-call-with-super [call this meth]
 (let [m (proxy-mappings this)]
    (update-proxy this (assoc m meth nil))
    (let [ret (call)]
      (update-proxy this m)
      ret)))

As a result the following sequence behaves unexpectedly:

(def obj (proxy [java.lang.ClassLoader] []
		      (loadClass [cl] (println "enter")
				 (proxy-super loadClass cl))))
(.loadClass obj "nonexistent")
;; prints enter, then throws ClassNotFoundException
(.loadClass obj "nonexistent")
;; does not print anything before throwing cnfe

Patch: clj-983-2.patch

Approach: Use a try-finally block around the invocation to perform the after invocation action regardless of exceptions.

Screened by: Stuart Sierra

  1. clj-983-2.patch
    06/Jan/14 3:06 PM
    2 kB
    Alex Miller
  2. proxy_super.patch
    05/May/12 9:04 AM
    2 kB
    Valentin Mahrwald

Activity

Hide
Valentin Mahrwald added a comment -

Test & fix patch on latest Clojure github branch.

Show
Valentin Mahrwald added a comment - Test & fix patch on latest Clojure github branch.
Valentin Mahrwald made changes -
Field Original Value New Value
Attachment proxy_super.patch [ 11171 ]
Alex Miller made changes -
Labels bug interop
Hide
Alex Miller added a comment -

Patch provider does not have a signed CA so can't be accepted as is.

Show
Alex Miller added a comment - Patch provider does not have a signed CA so can't be accepted as is.
Alex Miller made changes -
Patch Code and Test [ 10002 ]
Approval Triaged [ 10120 ]
Description The code for proxy-call-with-super internally used by proxy-super does not handle exceptions from the call method:

(defn proxy-call-with-super [call this meth]
 (let [m (proxy-mappings this)]
    (update-proxy this (assoc m meth nil))
    (let [ret (call)]
      (update-proxy this m)
      ret)))

As a result the following sequence behaves unexpectedly:
(def obj (proxy [java.lang.ClassLoader] []
(loadClass [cl] (println "enter")
(proxy-super loadClass cl))))
(.loadClass obj "nonexistent")
;; prints enter, then throws ClassNotFoundException
(.loadClass obj "nonexistent")
;; does not print anything before throwing cnfe


A try-finally block around the invocation would solve this particular issue.
The code for proxy-call-with-super internally used by proxy-super does not handle exceptions from the call method:

{code}
(defn proxy-call-with-super [call this meth]
 (let [m (proxy-mappings this)]
    (update-proxy this (assoc m meth nil))
    (let [ret (call)]
      (update-proxy this m)
      ret)))
{code}

As a result the following sequence behaves unexpectedly:
{code}
(def obj (proxy [java.lang.ClassLoader] []
(loadClass [cl] (println "enter")
(proxy-super loadClass cl))))
(.loadClass obj "nonexistent")
;; prints enter, then throws ClassNotFoundException
(.loadClass obj "nonexistent")
;; does not print anything before throwing cnfe
{code}

*Approach:* Use a try-finally block around the invocation to perform the after invocation action regardless of exceptions.
Priority Minor [ 4 ] Major [ 3 ]
Affects Version/s Release 1.5 [ 10150 ]
Hide
Alex Miller added a comment -

Marked vetted in 1.6 per Rich.

Show
Alex Miller added a comment - Marked vetted in 1.6 per Rich.
Alex Miller made changes -
Approval Triaged [ 10120 ] Vetted [ 10003 ]
Fix Version/s Release 1.6 [ 10157 ]
Hide
Alex Miller added a comment -

Incomplete - needs clean patch.

Show
Alex Miller added a comment - Incomplete - needs clean patch.
Alex Miller made changes -
Approval Vetted [ 10003 ] Incomplete [ 10006 ]
Hide
Alex Miller added a comment -

Added new clean patch for screening consideration.

Show
Alex Miller added a comment - Added new clean patch for screening consideration.
Alex Miller made changes -
Approval Incomplete [ 10006 ] Vetted [ 10003 ]
Description The code for proxy-call-with-super internally used by proxy-super does not handle exceptions from the call method:

{code}
(defn proxy-call-with-super [call this meth]
 (let [m (proxy-mappings this)]
    (update-proxy this (assoc m meth nil))
    (let [ret (call)]
      (update-proxy this m)
      ret)))
{code}

As a result the following sequence behaves unexpectedly:
{code}
(def obj (proxy [java.lang.ClassLoader] []
(loadClass [cl] (println "enter")
(proxy-super loadClass cl))))
(.loadClass obj "nonexistent")
;; prints enter, then throws ClassNotFoundException
(.loadClass obj "nonexistent")
;; does not print anything before throwing cnfe
{code}

*Approach:* Use a try-finally block around the invocation to perform the after invocation action regardless of exceptions.
The code for proxy-call-with-super internally used by proxy-super does not handle exceptions from the call method:

{code}
(defn proxy-call-with-super [call this meth]
 (let [m (proxy-mappings this)]
    (update-proxy this (assoc m meth nil))
    (let [ret (call)]
      (update-proxy this m)
      ret)))
{code}

As a result the following sequence behaves unexpectedly:
{code}
(def obj (proxy [java.lang.ClassLoader] []
(loadClass [cl] (println "enter")
(proxy-super loadClass cl))))
(.loadClass obj "nonexistent")
;; prints enter, then throws ClassNotFoundException
(.loadClass obj "nonexistent")
;; does not print anything before throwing cnfe
{code}

*Patch:* clj-983-2.patch

*Approach:* Use a try-finally block around the invocation to perform the after invocation action regardless of exceptions.
Attachment clj-983-2.patch [ 12598 ]
Hide
Stuart Sierra added a comment -

Screened OK.

Show
Stuart Sierra added a comment - Screened OK.
Stuart Sierra made changes -
Approval Vetted [ 10003 ] Screened [ 10004 ]
Description The code for proxy-call-with-super internally used by proxy-super does not handle exceptions from the call method:

{code}
(defn proxy-call-with-super [call this meth]
 (let [m (proxy-mappings this)]
    (update-proxy this (assoc m meth nil))
    (let [ret (call)]
      (update-proxy this m)
      ret)))
{code}

As a result the following sequence behaves unexpectedly:
{code}
(def obj (proxy [java.lang.ClassLoader] []
(loadClass [cl] (println "enter")
(proxy-super loadClass cl))))
(.loadClass obj "nonexistent")
;; prints enter, then throws ClassNotFoundException
(.loadClass obj "nonexistent")
;; does not print anything before throwing cnfe
{code}

*Patch:* clj-983-2.patch

*Approach:* Use a try-finally block around the invocation to perform the after invocation action regardless of exceptions.
The code for proxy-call-with-super internally used by proxy-super does not handle exceptions from the call method:

{code}
(defn proxy-call-with-super [call this meth]
 (let [m (proxy-mappings this)]
    (update-proxy this (assoc m meth nil))
    (let [ret (call)]
      (update-proxy this m)
      ret)))
{code}

As a result the following sequence behaves unexpectedly:
{code}
(def obj (proxy [java.lang.ClassLoader] []
(loadClass [cl] (println "enter")
(proxy-super loadClass cl))))
(.loadClass obj "nonexistent")
;; prints enter, then throws ClassNotFoundException
(.loadClass obj "nonexistent")
;; does not print anything before throwing cnfe
{code}

*Patch:* clj-983-2.patch

*Approach:* Use a try-finally block around the invocation to perform the after invocation action regardless of exceptions.

*Screened by:* Stuart Sierra
Rich Hickey made changes -
Approval Screened [ 10004 ] Ok [ 10007 ]
Stuart Halloway made changes -
Resolution Completed [ 1 ]
Status Open [ 1 ] Closed [ 6 ]

People

Vote (4)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: