Можно ли когда-нибудь «обмануть» Java-программу, приняв любую строку за ноль? - PullRequest
0 голосов
/ 09 марта 2019

Это вопрос интервью:

Предположим, вы кодируете систему Android, которая использует JNI и некоторый код C ++ для чтения данных с последовательного интерфейса (например, UART).

Материал нижнего уровня будет заботиться о коде C ++, и в конечном итоге данные будут передаваться в интерфейс Java, где они будут обрабатываться как тип String.

Вопрос: предположим, что код Java, обрабатывающий чтение, выглядит примерно так:

private void parseSerialData(String input){

 if (input==null){
//DO SOMETHING HERE
    }
}

Будет ли когда-либо возможно выполнение условий блока if?

Мое понимание Java говорит мне, что это никогда не будет возможно, потому что (я могу быть совершенно неправ), нуль в Java - это способ обозначить «нет ссылки», нуль не является объектом, и это не было создан из класса. На уровне DVM или JVM, пока переменная была объявлена, была сделана ссылка, даже если для нее в стеке не было выделенной памяти.

Следовательно, для локальной переменной как параметра метода невозможно иметь ссылку для начала, не говоря уже о том, что позже ей была дана ссылка на указатель на объект String (даже если этот объект может не иметь информация с ним, тем не менее, является ненулевым объектом) и, как таковое, условие if никогда не будет выполнено.

Но я не мог решить, является ли этот вопрос вопросом с подвохом, и я что-то пропустил? Особенно если учесть, что в драке есть C ++, и я понятия не имею, каково это передавать пустую ссылку C ++ на Java, если это вообще имеет смысл?

Итак, будет ли когда-либо выполнено условие?

1 Ответ

3 голосов
/ 09 марта 2019

Да, конечно, input может быть нулевым.Это просто зависит от того, что делает код C ++.Вот полный пример.Из вашего описания не было ясно, возвращает ли нативный метод String или передает его в качестве параметра из нативного метода в java-метод, поэтому я включил пример каждого из них.

Эта программа вызывает fпять раз.Первые три раза просто передают постоянное значение.Следующие два раза ожидают ввода (в собственном методе) и передают значение NULL или NULL в f в зависимости от того, является ли вход пустым или нет.

Test.java

public class Test
{
    static {
        System.loadLibrary("Test");
    }

    public static void main(String [] args)
    {
        Test obj = new Test();
        obj.main();
    }

    void main()
    {
        f(null);
        f("not null");
        String s1 = null;
        f(s1);
        String s2 = n1();
        f(s2);
        n2();
    }

    public void f(String s)
    {
        if (s == null)
            System.out.println("null");
        else
            System.out.println(s);
    }

    native String n1();
    native void n2();
}

Test.cc

#include <stdio.h>
#include <jni.h>
#include "Test.h"

static jstring get_string(JNIEnv *env);

JNIEXPORT jstring JNICALL Java_Test_n1(JNIEnv *env, jobject obj)
{
    return get_string(env);
}

JNIEXPORT void JNICALL Java_Test_n2(JNIEnv *env, jobject obj)
{
    jstring s = get_string(env);
    jclass cls = env->GetObjectClass(obj);
    jmethodID f = env->GetMethodID(cls, "f", "(Ljava/lang/String;)V");
    env->CallVoidMethod(obj, f, s);
}

static jstring get_string(JNIEnv *env)
{
    char buf[20];
    if (fgets(buf, sizeof buf, stdin) == NULL)
        return NULL;
    if (buf[0] == '\n')
        return NULL;
    return env->NewStringUTF(buf);
}

Инструкции по сборке

$ javac Test.java
$ javah Test
$ gcc --std=c++11 -I $JAVA_HOME/include -I $JAVA_HOME/include/linux  -fPIC -shared -o libTest.so Test.cc
$ /usr/bin/java -Djava.library.path=. Test
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...