mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-19 05:07:56 +00:00
Fix JNI argv parsing: throw exception on NULL
Add new 'jni' test case to ensure this works
This commit is contained in:
parent
e856cafc97
commit
788b3e37b2
@ -117,7 +117,8 @@ static int outv_end_field()
|
|||||||
return put_blob((jbyte *)outv_buffer, length);
|
return put_blob((jbyte *)outv_buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Throw(JNIEnv *env, const char *class, const char *msg){
|
int Throw(JNIEnv *env, const char *class, const char *msg)
|
||||||
|
{
|
||||||
jclass exceptionClass = NULL;
|
jclass exceptionClass = NULL;
|
||||||
if ((exceptionClass = (*env)->FindClass(env, class)) == NULL)
|
if ((exceptionClass = (*env)->FindClass(env, class)) == NULL)
|
||||||
return -1; // exception
|
return -1; // exception
|
||||||
@ -157,40 +158,36 @@ JNIEXPORT jint JNICALL Java_org_servalproject_servald_ServalD_rawCommand(JNIEnv
|
|||||||
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method totalRowCount");
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method totalRowCount");
|
||||||
}
|
}
|
||||||
unsigned char status = 0; // to match what the shell gets: 0..255
|
unsigned char status = 0; // to match what the shell gets: 0..255
|
||||||
|
|
||||||
if (jni_env)
|
if (jni_env)
|
||||||
return Throw(env, "java/lang/IllegalStateException", "re-entrancy not supported");
|
return Throw(env, "java/lang/IllegalStateException", "re-entrancy not supported");
|
||||||
|
|
||||||
// Construct argv, argc from this method's arguments.
|
// Construct argv, argc from this method's arguments.
|
||||||
jsize len = (*env)->GetArrayLength(env, args);
|
jsize len = (*env)->GetArrayLength(env, args);
|
||||||
const char **argv = alloca(sizeof(char*) * (len + 1));
|
const char **argv = alloca(sizeof(char*) * (len + 1));
|
||||||
if (argv == NULL)
|
if (argv == NULL)
|
||||||
return Throw(env, "java/lang/OutOfMemoryError", "alloca returned NULL");
|
return Throw(env, "java/lang/OutOfMemoryError", "alloca() returned NULL");
|
||||||
|
|
||||||
argv[len]=NULL;
|
|
||||||
|
|
||||||
jsize i;
|
jsize i;
|
||||||
|
for (i = 0; i <= len; ++i)
|
||||||
|
argv[i] = NULL;
|
||||||
int argc = len;
|
int argc = len;
|
||||||
// From now on, in case of an exception we have to free some resources before
|
// From now on, in case of an exception we have to free some resources before
|
||||||
// returning.
|
// returning.
|
||||||
jni_exception = 0;
|
jni_exception = 0;
|
||||||
const char *empty="";
|
for (i = 0; !jni_exception && i < len; ++i) {
|
||||||
|
|
||||||
for (i = 0; i < len; ++i) {
|
|
||||||
const jstring arg = (jstring)(*env)->GetObjectArrayElement(env, args, i);
|
const jstring arg = (jstring)(*env)->GetObjectArrayElement(env, args, i);
|
||||||
if ((*env)->ExceptionOccurred(env))
|
if ((*env)->ExceptionOccurred(env))
|
||||||
jni_exception = 1;
|
jni_exception = 1;
|
||||||
|
else if (arg == NULL) {
|
||||||
argv[i] = empty;
|
Throw(env, "java/lang/NullPointerException", "null element in argv");
|
||||||
if (arg != NULL && !jni_exception){
|
jni_exception = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
const char *str = (*env)->GetStringUTFChars(env, arg, NULL);
|
const char *str = (*env)->GetStringUTFChars(env, arg, NULL);
|
||||||
if (str == NULL){
|
if (str == NULL)
|
||||||
jni_exception = 1;
|
jni_exception = 1;
|
||||||
}else
|
else
|
||||||
argv[i] = str;
|
argv[i] = str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!jni_exception) {
|
if (!jni_exception) {
|
||||||
// Set up the output buffer.
|
// Set up the output buffer.
|
||||||
jniResults = outv;
|
jniResults = outv;
|
||||||
@ -200,10 +197,9 @@ JNIEXPORT jint JNICALL Java_org_servalproject_servald_ServalD_rawCommand(JNIEnv
|
|||||||
status = parseCommandLine(NULL, argc, argv);
|
status = parseCommandLine(NULL, argc, argv);
|
||||||
jni_env = NULL;
|
jni_env = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release argv Java string buffers.
|
// Release argv Java string buffers.
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
if (argv[i] && argv[i]!=empty) {
|
if (argv[i]) {
|
||||||
const jstring arg = (jstring)(*env)->GetObjectArrayElement(env, args, i);
|
const jstring arg = (jstring)(*env)->GetObjectArrayElement(env, args, i);
|
||||||
(*env)->ReleaseStringUTFChars(env, arg, argv[i]);
|
(*env)->ReleaseStringUTFChars(env, arg, argv[i]);
|
||||||
}
|
}
|
||||||
|
@ -34,5 +34,23 @@ class ServalDTests
|
|||||||
}
|
}
|
||||||
System.out.println("");
|
System.out.println("");
|
||||||
}
|
}
|
||||||
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void nullArg(String[] args)
|
||||||
|
{
|
||||||
|
ServalD servald = new ServalD();
|
||||||
|
for (int i = 0; i != args.length; ++i)
|
||||||
|
if ("(null)".equals(args[i]))
|
||||||
|
args[i] = null;
|
||||||
|
servald.command(Arrays.copyOfRange(args, 0, args.length));
|
||||||
|
System.out.print(servald.status);
|
||||||
|
for (byte[] a: servald.outv) {
|
||||||
|
System.out.print(":");
|
||||||
|
System.out.print(new String(a));
|
||||||
|
}
|
||||||
|
System.out.println("");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
13
tests/jni
13
tests/jni
@ -47,7 +47,7 @@ assert_echo_works() {
|
|||||||
|
|
||||||
doc_Echo="Serval JNI echo Hello world"
|
doc_Echo="Serval JNI echo Hello world"
|
||||||
test_Echo() {
|
test_Echo() {
|
||||||
executeOk java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalD echo -e 'Hello,\ttab' 'world\0!'
|
executeOk java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalD 'echo' '-e' 'Hello,\ttab' 'world\0!'
|
||||||
assertStdoutIs -e 'Hello,\ttab\nworld\0!\n'
|
assertStdoutIs -e 'Hello,\ttab\nworld\0!\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,9 +64,18 @@ test_Delim() {
|
|||||||
|
|
||||||
doc_Repeat="Serval JNI repeated calls in same process"
|
doc_Repeat="Serval JNI repeated calls in same process"
|
||||||
test_Repeat() {
|
test_Repeat() {
|
||||||
executeOk java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalDTests repeat 50 echo 'Hello,' 'world!'
|
executeOk --core-backtrace java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalDTests repeat 50 'echo' 'Hello,' 'world!'
|
||||||
assertStdoutLineCount '==' 50
|
assertStdoutLineCount '==' 50
|
||||||
assertStdoutGrep --matches=50 '^0:Hello,:world!$'
|
assertStdoutGrep --matches=50 '^0:Hello,:world!$'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc_NullArg="Serval JNI null arguments throw exception"
|
||||||
|
test_NullArg() {
|
||||||
|
execute --core-backtrace java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalDTests nullArg 'echo' '(null)'
|
||||||
|
tfw_cat --stdout --stderr
|
||||||
|
assertExitStatus '!=' 0
|
||||||
|
assertStderrGrep 'NullPointerException: null element in argv'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
runTests "$@"
|
runTests "$@"
|
||||||
|
Loading…
Reference in New Issue
Block a user