Bug 23440 - Can't return a empty List
Summary: Can't return a empty List
Status: RESOLVED MOVED
Alias: None
Product: dbus
Classification: Unclassified
Component: java (show other bugs)
Version: 1.2.x
Hardware: x86 (IA32) Linux (All)
: medium critical
Assignee: Matthew Johnson
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-08-21 08:46 UTC by Pawel Szklarz
Modified: 2018-10-12 21:01 UTC (History)
3 users (show)

See Also:
i915 platform:
i915 features:


Attachments
A simple call to MethodCall( ... "a(sss)", new ArrayList<AStruct>() ) (705 bytes, text/plain)
2011-08-29 00:52 UTC, xtofl
Details
a failing standalone test case (1.49 KB, text/x-java)
2012-03-29 05:18 UTC, Olivier Tilloy
Details
patch that fixes the above test case (634 bytes, patch)
2012-03-29 05:19 UTC, Olivier Tilloy
Details | Splinter Review

Description Pawel Szklarz 2009-08-21 08:46:09 UTC
Testing the implementation of:
<method name="getAllProcess">
<arg type="a(ssss)" name="listProcess" direction="out"/>
</method>

I am returning a empty list.

The client gets the error:

org.freedesktop.dbus.exceptions.DBusExecutionException: Error Executing Method com.pmsoft.eserv.nec.core.bis.ProcessRejestry.getAllProcess: 1
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
.......

In the server site, I get exception
java.lang.ArrayIndexOutOfBoundsException: 1

on class 
org.freedesktop.dbus.Message, 
method 
public void append(String sig, Object... data) throws DBusException
line 777:
      for (int i = 0; i < sigb.length; i++) {
         if (Debug.debug) Debug.print(.....
         i = appendone(sigb, i, data[j++]);  <<<< here
      }


Debugint dbus-java library i found that in class org.freedesktop.dbus.Message, method "appendone", starting from line 624, the follow code generates the real problem

  } else if (data instanceof List) {
   Object[] contents = ((List) data).toArray();
   int diff = i;
   ensureBuffers(contents.length*4);
   for (Object o: contents) 
      diff = appendone(sigb, i, o); <<<not executed for empty list!!!
   i = diff;
} else if....

For empty list, the marked code is not executed, so, diff is not calculated.
In the case of "a(ssss)", diff should be 1+4.
As a result, the return value from appenddone is 1 and not 5, and appenddone is executed one more time. data[2] gives the ArrayIndexOutOfBoundsException.


I am using dbus-java 2.6.
In the git repositorium the code is the same.


The problem is solved for the "data instanceof Map" case with the code:
                  if (i == diff) {
                     // advance the type parser even on 0-size arrays.
                     Vector<Type> temp = new Vector<Type>();
                     byte[] temp2 = new byte[sigb.length-diff];
                     System.arraycopy(sigb, diff, temp2, 0, temp2.length);
                     String temp3 = new String(temp2);
                     int temp4 = Marshalling.getJavaType(temp3, temp, 1);
                     diff += temp4;
                  }

Using exacly the same code for the list case, the request is returning and the client gets a empty list.
Comment 1 xtofl 2011-08-29 00:49:22 UTC
The proposed solution works, of course, but I believe it would be better to write the 'type parsing' code only once.  No matter how many elements are in the provided container, the type should be parsed.
Comment 2 xtofl 2011-08-29 00:52:10 UTC
Created attachment 50646 [details]
A simple call to MethodCall( ... "a(sss)", new ArrayList<AStruct>() )


This is the trivial case of the MethodCall with "a(...)" arguments.
Comment 3 xtofl 2011-08-31 03:58:34 UTC
Switched the 'importance' to 'critical' because the same pattern is present throughout the whole Message.appendone code.
Comment 4 Olivier Tilloy 2012-03-29 05:18:14 UTC
Created attachment 59222 [details]
a failing standalone test case
Comment 5 Olivier Tilloy 2012-03-29 05:19:22 UTC
Created attachment 59223 [details] [review]
patch that fixes the above test case
Comment 6 Olivier Tilloy 2012-03-29 05:20:01 UTC
It looks like the fix suggested by Pawel Szklarz was applied and released with version 2.8, although the git repository on freedesktop.org doesn’t seem to contain this change and the release, as far as I can tell from http://cgit.freedesktop.org/dbus/dbus-java/. The status of this bug report hasn’t been updated either.

I’m running version 2.8 on Ubuntu, and I found that the fix that was applied solves the problem only partially. I attached a simple standalone test case that fails with version 2.8, along with a patch that fixes it.
To run the test, just compile Test.java, and run it with `javac Test`. Then in a terminal run:

    dbus-send --session --dest=net.osomon.test --print-reply \
        /net/osomon/test net.osomon.test.getTestStructWithEmptyArray

About the patch I attached, I tracked the issue down to a problem in the implementation of Marshalling.getJavaType(…): it is supposed to return the number of characters parsed from the type string. When passed "(i))" with a limit of 1 (which is what happens when called from Message.appendone(…) when marshalling an empty list of structs), it correctly parses the structure "(i)", but it returns 4, where it should have returned 3. This is because the variable j holds the index of the character in the signature just after the last one that was parsed. Variable i is assigned the value of j, and just after that it is incremented as part of the enclosing for loop, and as a result has a value of (total_chars_parsed + 1).

I haven’t noticed any regressions so far, but obviously a thorough review would be very welcome.
Comment 7 Jean Parpaillon 2016-07-05 07:38:19 UTC
I have included this patch in a fork of dbus-java on github:
https://github.com/jeanparpaillon/dbus-java/commit/1ef913289b92db755a3cdb30a70c4d34d0057fd4
Comment 8 GitLab Migration User 2018-10-12 21:01:52 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/dbus/dbus-java/issues/2.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.