[libvirt] [PATCH] [libvirt-java] Fix Array IndexOutOfBoundsException for unknown error codes

Claudio Bley cbley at av-test.de
Wed Aug 1 14:11:20 UTC 2012


At Mon, 23 Jul 2012 14:56:55 -0600,
Eric Blake wrote:
> 
> On 07/23/2012 04:31 AM, Claudio Bley wrote:
> >> When libvirt returns an error code which is not mapped in enum
> >> ErrorNumber, an IndexOutOfBoundsException is thrown.
> >>
> >> I realize that the freshly released libvirt-java 0.4.8 supports all
> >> error codes up to libvirt 0.9.12. But that doesn't fix the problem.
> >>
> >> Would it be feasible to add a special UNKNOWN enum value?
> 
> I think that might be better, after all.  With your patch...
> 
> >      public Error(virError vError) {
> > -        code = ErrorNumber.values()[vError.code];
> > -        domain = ErrorDomain.values()[vError.domain];
> > -        level = ErrorLevel.values()[vError.level];
> > +        if (ErrorNumber.values().length > vError.code)
> > +            code = ErrorNumber.values()[vError.code];
> 
> the old version crashed, and your version leaves code as null (which is
> a strict improvement, but might cause its own NullPointer issue later
> on).  Having an else branch that sticks in a placeholder would be nicer
> to end clients to at least recognize that they are talking to a newer
> server, without crashing.

Please have look at the following patch.

-- >8 --
Subject: [PATCH] Fix IndexOutOfBoundsException for unknown error
 number/domain/level codes.

Remove default constructor because it does not init the object properly.

Add a special *_UNKNOWN enum value to each enum which is used when the
given enum code is out of bounds.
---
 src/main/java/org/libvirt/Error.java | 42 +++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/libvirt/Error.java b/src/main/java/org/libvirt/Error.java
index f185ce0..a345b82 100644
--- a/src/main/java/org/libvirt/Error.java
+++ b/src/main/java/org/libvirt/Error.java
@@ -12,6 +12,20 @@ import org.libvirt.jna.virError;
  */
 public class Error implements Serializable {
 
+    /**
+     * Map an integer to an enum value.
+     *
+     * @return when {@code n < values.length} return n-th item of
+     *          {@code values}, otherwise the last item of array
+     *          {@code values}.
+     */
+    private static final <T extends Enum<T>> T wrapToEnum(final int n, final T[] values) {
+        assert(n >= 0 && values.length > 0);
+
+        int idx = Math.min(n, values.length - 1);
+        return values[idx];
+    }
+
     public static enum ErrorDomain {
         VIR_FROM_NONE, VIR_FROM_XEN, /* Error at Xen hypervisor layer */
         VIR_FROM_XEND, /* Error at connection with xend daemon */
@@ -60,6 +74,11 @@ public class Error implements Serializable {
         VIR_FROM_URI, /* Error from URI handling */
         VIR_FROM_AUTH, /* Error from auth handling */
         VIR_FROM_DBUS, /* Error from DBus */
+        VIR_FROM_UNKNOWN; /* unknown error domain (must be the last entry!) */
+
+        protected static final ErrorDomain wrap(int value) {
+            return wrapToEnum(value, values());
+        }
     }
 
     public static enum ErrorLevel {
@@ -71,7 +90,13 @@ public class Error implements Serializable {
         /**
          * An error
          */
-        VIR_ERR_ERROR
+        VIR_ERR_ERROR,
+
+        VIR_ERR_UNKNOWN; /* must be the last entry! */
+
+        protected static final ErrorLevel wrap(int value) {
+            return wrapToEnum(value, values());
+        }
     }
 
     public static enum ErrorNumber {
@@ -161,6 +186,11 @@ public class Error implements Serializable {
         VIR_ERR_MIGRATE_UNSAFE, /* Migration is not safe */
         VIR_ERR_OVERFLOW, /* integer overflow */
         VIR_ERR_BLOCK_COPY_ACTIVE, /* action prevented by block copy job */
+        VIR_ERR_UNKNOWN; /* unknown error (must be the last entry!) */
+
+        protected static final ErrorNumber wrap(int value) {
+            return wrapToEnum(value, values());
+        }
     }
 
     /**
@@ -181,14 +211,10 @@ public class Error implements Serializable {
     int int2;
     NetworkPointer VNP; /* Deprecated */
 
-    public Error() {
-
-    }
-
     public Error(virError vError) {
-        code = ErrorNumber.values()[vError.code];
-        domain = ErrorDomain.values()[vError.domain];
-        level = ErrorLevel.values()[vError.level];
+        code = code.wrap(vError.code);
+        domain = domain.wrap(vError.domain);
+        level = level.wrap(vError.level);
         message = vError.message;
         str1 = vError.str1;
         str2 = vError.str2;
-- 
1.7.11.msysgit.0

-- 
AV-Test GmbH, Henricistraße 20, 04155 Leipzig, Germany
Phone: +49 341 265 310 19
Web:<http://www.av-test.org>

Eingetragen am / Registered at: Amtsgericht Stendal (HRB 114076)
Geschaeftsfuehrer (CEO): Andreas Marx, Guido Habicht, Maik Morgenstern




More information about the libvir-list mailing list