Merge pull request #250 from gasbytes/SSLEngine-patch

fix: handle DirectByteBuffers in WolfSSLSession.read()
pull/249/head
Chris Conlon 2025-01-10 11:50:30 -07:00 committed by GitHub
commit e600b0f056
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 57 additions and 50 deletions

View File

@ -1215,75 +1215,82 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff
return -1; return -1;
} }
/* ByteBuffer.hasArray() does not throw any exceptions */
hasArray = (*jenv)->CallBooleanMethod(jenv, buf, hasArrayMeth);
if (!hasArray) {
(*jenv)->ThrowNew(jenv, excClass,
"ByteBuffer.hasArray() is false in native read()");
return BAD_FUNC_ARG;
}
/* Only read up to maximum space we have in this ByteBuffer */ /* Only read up to maximum space we have in this ByteBuffer */
maxOutputSz = (limit - position); maxOutputSz = (limit - position);
if (outSz > maxOutputSz) { if (outSz > maxOutputSz) {
outSz = maxOutputSz; outSz = maxOutputSz;
} }
/* Get reference to underlying byte[] from ByteBuffer */ hasArray = (*jenv)->CallBooleanMethod(jenv, buf, hasArrayMeth);
arrayMeth = (*jenv)->GetMethodID(jenv, buffClass, "array", "()[B");
if (arrayMeth == NULL) { if (hasArray) {
/* Get reference to underlying byte[] from ByteBuffer */
arrayMeth = (*jenv)->GetMethodID(jenv, buffClass, "array", "()[B");
if (arrayMeth == NULL) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Failed to find ByteBuffer array() method in native read()");
return -1;
}
bufArr = (jbyteArray)(*jenv)->CallObjectMethod(jenv, buf, arrayMeth);
/* Get array elements */
data = (byte *)(*jenv)->GetByteArrayElements(jenv, bufArr, NULL);
if ((*jenv)->ExceptionOccurred(jenv)) { if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv); (*jenv)->ExceptionClear(jenv);
(*jenv)->ThrowNew(jenv, excClass,
"Exception when calling ByteBuffer.array() in native read()");
return -1;
} }
(*jenv)->ThrowNew(jenv, excClass,
"Failed to find ByteBuffer array() method in native read()");
return -1;
} }
bufArr = (jbyteArray)(*jenv)->CallObjectMethod(jenv, buf, arrayMeth); else {
data = (byte *)(*jenv)->GetDirectBufferAddress(jenv, buf);
/* Get array elements */ if (data == NULL) {
data = (byte*)(*jenv)->GetByteArrayElements(jenv, bufArr, NULL); (*jenv)->ThrowNew(jenv, excClass,
if ((*jenv)->ExceptionOccurred(jenv)) { "Failed to get DirectBuffer address in native read()");
(*jenv)->ExceptionDescribe(jenv); return BAD_FUNC_ARG;
(*jenv)->ExceptionClear(jenv); }
(*jenv)->ThrowNew(jenv, excClass,
"Exception when calling ByteBuffer.array() in native read()");
return -1;
} }
if (data != NULL) { if (data != NULL) {
size = SSLReadNonblockingWithSelectPoll(ssl, data + position, size = SSLReadNonblockingWithSelectPoll(ssl, data + position,
maxOutputSz, (int)timeout); maxOutputSz, (int)timeout);
/* Relase array elements */ /* Relase array elements */
if (size < 0) { if (hasArray) {
(*jenv)->ReleaseByteArrayElements(jenv, bufArr, (jbyte*)data, if (size < 0) {
JNI_ABORT); (*jenv)->ReleaseByteArrayElements(jenv, bufArr, (jbyte *)data,
} JNI_ABORT);
else {
/* JNI_COMMIT commits the data but does not free the local array
* 0 is used here to both commit and free */
(*jenv)->ReleaseByteArrayElements(jenv, bufArr,
(jbyte*)data, 0);
/* Update ByteBuffer position() based on bytes written */
setPositionMeth = (*jenv)->GetMethodID(jenv, buffClass,
"position", "(I)Ljava/nio/Buffer;");
if (setPositionMeth == NULL) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Failed to set ByteBuffer position() from "
"native read()");
size = -1;
} }
else { else {
(*jenv)->CallVoidMethod(jenv, buf, setPositionMeth, (*jenv)->ReleaseByteArrayElements(jenv, bufArr,
position + size); (jbyte *)data, 0);
}
}
/* Note: DirectByteBuffer doesn't need releasing data */
if (size > 0) {
/* Update ByteBuffer position() based on bytes written */
setPositionMeth = (*jenv)->GetMethodID(jenv, buffClass,
"position", "(I)Ljava/nio/Buffer;");
if (setPositionMeth == NULL) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Failed to set ByteBuffer position() from "
"native read()");
size = -1;
}
else {
(*jenv)->CallVoidMethod(jenv, buf, setPositionMeth,
position + size);
} }
} }
} }