[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: JavaHL bug in native code?

From: Philip Martin <philip.martin_at_wandisco.com>
Date: Wed, 21 Dec 2011 00:53:16 +0000

Mark Phippard <markphip_at_gmail.com> writes:

> On Tue, Dec 20, 2011 at 2:42 PM, Philip Martin
> <philip.martin_at_wandisco.com> wrote:
>> Mark Phippard <markphip_at_gmail.com> writes:
>>
>>> We have had a few users report a weird error that looks like they are
>>> getting an ArrayIndexOutOfBoundsException except that it appears that
>>> it is coming out of the native code. This happens during an update
>>> operation. I am going to paste some of the native code in here, in
>>> case anyone sees anything in the array handling that looks wrong. The
>>> use of ++i instead of i++ looks odd to me, but I am not a C++
>>> programmer and the general code patterns.
>>
>> ++i and i++ are equivalent in this case, and likely to be identical
>> after optimisation.
>>
>>>
>>> const apr_array_header_t *array = targets.array(subPool);
>>> SVN_JNI_ERR(targets.error_occured(), NULL);
>>> SVN_JNI_ERR(svn_client_update4(&revs, array,
>>> revision.revision(),
>>> depth,
>>> depthIsSticky,
>>> ignoreExternals,
>>> allowUnverObstructions,
>>> TRUE /* adds_as_modification */,
>>> makeParents,
>>> ctx, subPool.getPool()),
>>> NULL);
>>>
>>> JNIEnv *env = JNIUtil::getEnv();
>>> jlongArray jrevs = env->NewLongArray(revs->nelts);
>>> if (JNIUtil::isJavaExceptionThrown())
>>> return NULL;
>>> jlong *jrevArray = env->GetLongArrayElements(jrevs, NULL);
>>> if (JNIUtil::isJavaExceptionThrown())
>>> return NULL;
>>> for (int i = 0; i < revs->nelts; ++i)
>>> {
>>> jlong rev = APR_ARRAY_IDX(revs, i, svn_revnum_t);
>>> jrevArray[i] = rev;
>>> }
>>> env->ReleaseLongArrayElements(jrevs, jrevArray, 0);
>>
>> Do we need to consider ReleaseLongArrayElements raising an exception?
>>
>> Everything else looks OK.
>>
>>> return jrevs;
>
>
> The Subclipse code always calls this API with an array of exactly one
> path. I only see two arrays in this code. The list of paths to
> update, and the return value for revisions.

I suppose you could add a check to the bindings code to test whether
revs->nelts == array->nelts == 1.

> Is there ever a scenario where passing a single path to the API should
> return an array of 68ish revisions? Our code only ever looks at the
> first revision returned since our API wrapper only accepts a single
> path.

I'm a bit confused, I thought you stated that looking at element 68
caused a ArrayIndexOutOfBoundsException? Now you say you only ever look
at element 0?

The size of the jrevs array is set by the call the NewLongArray. If
revs->nelts was 68 at that point then the Java array would have 68
elements. The element values might be junk, but they would exist so I
don't see how that would lead to ArrayIndexOutOfBoundsException.

I suppose some other thread could clear the parent of the subpool
between the call to NewLongArray and the for loop. That would allow the
memory used by revs->nelts, which is allocated from the subpool, to be
reused. Then the value of revs->nelts might be "wrong" during the for
loop and that might corrupt the heap.

Or I suppose it could be unrelated heap corruption that happens to touch
the memory used by the Java array.

-- 
uberSVN: Apache Subversion Made Easy
http://www.uberSVN.com
Received on 2011-12-21 01:53:53 CET

This is an archived mail posted to the Subversion Dev mailing list.