Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46358df6 authored by Yang Ni's avatar Yang Ni Committed by Gerrit Code Review
Browse files

Merge "Sanity checks in JNI code for closure creation"

parents a51f14d0 4e90b9b5
Loading
Loading
Loading
Loading
+15 −3
Original line number Original line Diff line number Diff line
@@ -302,8 +302,12 @@ public class RenderScript {
        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
        long[] depFieldIDs) {
        long[] depFieldIDs) {
      validate();
      validate();
      return rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
      long c = rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
          sizes, depClosures, depFieldIDs);
          sizes, depClosures, depFieldIDs);
      if (c == 0) {
          throw new RSRuntimeException("Failed creating closure.");
      }
      return c;
    }
    }


    native long rsnInvokeClosureCreate(long con, long invokeID, byte[] params,
    native long rsnInvokeClosureCreate(long con, long invokeID, byte[] params,
@@ -311,8 +315,12 @@ public class RenderScript {
    synchronized long nInvokeClosureCreate(long invokeID, byte[] params,
    synchronized long nInvokeClosureCreate(long invokeID, byte[] params,
        long[] fieldIDs, long[] values, int[] sizes) {
        long[] fieldIDs, long[] values, int[] sizes) {
      validate();
      validate();
      return rsnInvokeClosureCreate(mContext, invokeID, params, fieldIDs,
      long c = rsnInvokeClosureCreate(mContext, invokeID, params, fieldIDs,
          values, sizes);
          values, sizes);
      if (c == 0) {
          throw new RSRuntimeException("Failed creating closure.");
      }
      return c;
    }
    }


    native void rsnClosureSetArg(long con, long closureID, int index,
    native void rsnClosureSetArg(long con, long closureID, int index,
@@ -337,7 +345,11 @@ public class RenderScript {
    synchronized long nScriptGroup2Create(String name, String cachePath,
    synchronized long nScriptGroup2Create(String name, String cachePath,
                                          long[] closures) {
                                          long[] closures) {
      validate();
      validate();
      return rsnScriptGroup2Create(mContext, name, cachePath, closures);
      long g = rsnScriptGroup2Create(mContext, name, cachePath, closures);
      if (g == 0) {
          throw new RSRuntimeException("Failed creating script group.");
      }
      return g;
    }
    }


    native void rsnScriptGroup2Execute(long con, long groupID);
    native void rsnScriptGroup2Execute(long con, long groupID);
+165 −43
Original line number Original line Diff line number Diff line
@@ -44,6 +44,9 @@


//#define LOG_API ALOGE
//#define LOG_API ALOGE
static constexpr bool kLogApi = false;
static constexpr bool kLogApi = false;
static constexpr size_t kMaxNumberArgsAndBindings = 1000;
static constexpr size_t kMaxNumberClosuresInScriptGroup = 1000000;
static constexpr size_t kMaxNumberKernelArguments = 256;


using namespace android;
using namespace android;


@@ -333,79 +336,167 @@ nClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong kernelID,
               jlong returnValue, jlongArray fieldIDArray,
               jlong returnValue, jlongArray fieldIDArray,
               jlongArray valueArray, jintArray sizeArray,
               jlongArray valueArray, jintArray sizeArray,
               jlongArray depClosureArray, jlongArray depFieldIDArray) {
               jlongArray depClosureArray, jlongArray depFieldIDArray) {
  jlong ret = 0;

  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
  RsScriptFieldID* fieldIDs =
  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
  jsize values_length = _env->GetArrayLength(valueArray);
  for (int i = 0; i< fieldIDs_length; i++) {
  jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
  jsize sizes_length = _env->GetArrayLength(sizeArray);
  jlong* jDepClosures =
      _env->GetLongArrayElements(depClosureArray, nullptr);
  jsize depClosures_length = _env->GetArrayLength(depClosureArray);
  jlong* jDepFieldIDs =
      _env->GetLongArrayElements(depFieldIDArray, nullptr);
  jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);

  size_t numValues, numDependencies;
  RsScriptFieldID* fieldIDs;
  uintptr_t* values;
  RsClosure* depClosures;
  RsScriptFieldID* depFieldIDs;

  if (fieldIDs_length != values_length || values_length != sizes_length) {
      ALOGE("Unmatched field IDs, values, and sizes in closure creation.");
      goto exit;
  }

  numValues = (size_t)fieldIDs_length;

  if (depClosures_length != depFieldIDs_length) {
      ALOGE("Unmatched closures and field IDs for dependencies in closure creation.");
      goto exit;
  }

  numDependencies = (size_t)depClosures_length;

  if (numDependencies > numValues) {
      ALOGE("Unexpected number of dependencies in closure creation");
      goto exit;
  }

  if (numValues > kMaxNumberArgsAndBindings) {
      ALOGE("Too many arguments or globals in closure creation");
      goto exit;
  }

  fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
  if (fieldIDs == nullptr) {
      goto exit;
  }

  for (size_t i = 0; i < numValues; i++) {
    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
  }
  }


  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
  values = (uintptr_t*)alloca(sizeof(uintptr_t) * numValues);
  jsize values_length = _env->GetArrayLength(valueArray);
  if (values == nullptr) {
  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
      goto exit;
  for (int i = 0; i < values_length; i++) {
  }

  for (size_t i = 0; i < numValues; i++) {
    values[i] = (uintptr_t)jValues[i];
    values[i] = (uintptr_t)jValues[i];
  }
  }


  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
  depClosures = (RsClosure*)alloca(sizeof(RsClosure) * numDependencies);
  jsize sizes_length = _env->GetArrayLength(sizeArray);
  if (depClosures == nullptr) {
      goto exit;
  }


  jlong* jDepClosures =
  for (size_t i = 0; i < numDependencies; i++) {
      _env->GetLongArrayElements(depClosureArray, nullptr);
  jsize depClosures_length = _env->GetArrayLength(depClosureArray);
  RsClosure* depClosures =
      (RsClosure*)alloca(sizeof(RsClosure) * depClosures_length);
  for (int i = 0; i < depClosures_length; i++) {
    depClosures[i] = (RsClosure)jDepClosures[i];
    depClosures[i] = (RsClosure)jDepClosures[i];
  }
  }


  jlong* jDepFieldIDs =
  depFieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numDependencies);
      _env->GetLongArrayElements(depFieldIDArray, nullptr);
  if (depFieldIDs == nullptr) {
  jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);
      goto exit;
  RsScriptFieldID* depFieldIDs =
  }
      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * depFieldIDs_length);

  for (int i = 0; i < depClosures_length; i++) {
  for (size_t i = 0; i < numDependencies; i++) {
    depFieldIDs[i] = (RsClosure)jDepFieldIDs[i];
    depFieldIDs[i] = (RsClosure)jDepFieldIDs[i];
  }
  }


  return (jlong)(uintptr_t)rsClosureCreate(
  ret = (jlong)(uintptr_t)rsClosureCreate(
      (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
      (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
      fieldIDs, numValues, values, numValues,
      (int*)sizes, (size_t)sizes_length,
      (int*)jSizes, numValues,
      depClosures, (size_t)depClosures_length,
      depClosures, numDependencies,
      depFieldIDs, (size_t)depFieldIDs_length);
      depFieldIDs, numDependencies);

exit:

  _env->ReleaseLongArrayElements(depFieldIDArray, jDepFieldIDs, JNI_ABORT);
  _env->ReleaseLongArrayElements(depClosureArray, jDepClosures, JNI_ABORT);
  _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
  _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
  _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);

  return ret;
}
}


static jlong
static jlong
nInvokeClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong invokeID,
nInvokeClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong invokeID,
                     jbyteArray paramArray, jlongArray fieldIDArray, jlongArray valueArray,
                     jbyteArray paramArray, jlongArray fieldIDArray, jlongArray valueArray,
                     jintArray sizeArray) {
                     jintArray sizeArray) {
  jlong ret = 0;

  jbyte* jParams = _env->GetByteArrayElements(paramArray, nullptr);
  jbyte* jParams = _env->GetByteArrayElements(paramArray, nullptr);
  jsize jParamLength = _env->GetArrayLength(paramArray);
  jsize jParamLength = _env->GetArrayLength(paramArray);

  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
  RsScriptFieldID* fieldIDs =
  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
  jsize values_length = _env->GetArrayLength(valueArray);
  for (int i = 0; i< fieldIDs_length; i++) {
  jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
  jsize sizes_length = _env->GetArrayLength(sizeArray);

  size_t numValues;
  RsScriptFieldID* fieldIDs;
  uintptr_t* values;

  if (fieldIDs_length != values_length || values_length != sizes_length) {
      ALOGE("Unmatched field IDs, values, and sizes in closure creation.");
      goto exit;
  }

  numValues = (size_t) fieldIDs_length;

  if (numValues > kMaxNumberArgsAndBindings) {
      ALOGE("Too many arguments or globals in closure creation");
      goto exit;
  }

  fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
  if (fieldIDs == nullptr) {
      goto exit;
  }

  for (size_t i = 0; i< numValues; i++) {
    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
  }
  }


  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
  values = (uintptr_t*)alloca(sizeof(uintptr_t) * numValues);
  jsize values_length = _env->GetArrayLength(valueArray);
  if (values == nullptr) {
  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
      goto exit;
  for (int i = 0; i < values_length; i++) {
    values[i] = (uintptr_t)jValues[i];
  }
  }


  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
  for (size_t i = 0; i < numValues; i++) {
  jsize sizes_length = _env->GetArrayLength(sizeArray);
    values[i] = (uintptr_t)jValues[i];
  }


  return (jlong)(uintptr_t)rsInvokeClosureCreate(
  ret = (jlong)(uintptr_t)rsInvokeClosureCreate(
      (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
      (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
      fieldIDs, numValues, values, numValues,
      (int*)sizes, (size_t)sizes_length);
      (int*)jSizes, numValues);

exit:

  _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
  _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
  _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);
  _env->ReleaseByteArrayElements(paramArray,      jParams,      JNI_ABORT);

  return ret;
}
}


static void
static void
@@ -425,20 +516,40 @@ nClosureSetGlobal(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
static long
static long
nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con, jstring name,
nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con, jstring name,
                    jstring cacheDir, jlongArray closureArray) {
                    jstring cacheDir, jlongArray closureArray) {
  jlong ret = 0;

  AutoJavaStringToUTF8 nameUTF(_env, name);
  AutoJavaStringToUTF8 nameUTF(_env, name);
  AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
  AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);


  jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
  jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
  jsize numClosures = _env->GetArrayLength(closureArray);
  jsize numClosures = _env->GetArrayLength(closureArray);
  RsClosure* closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);

  RsClosure* closures;

  if (numClosures > (jsize) kMaxNumberClosuresInScriptGroup) {
    ALOGE("Too many closures in script group");
    goto exit;
  }

  closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
  if (closures == nullptr) {
      goto exit;
  }

  for (int i = 0; i < numClosures; i++) {
  for (int i = 0; i < numClosures; i++) {
    closures[i] = (RsClosure)jClosures[i];
    closures[i] = (RsClosure)jClosures[i];
  }
  }


  return (jlong)(uintptr_t)rsScriptGroup2Create(
  ret = (jlong)(uintptr_t)rsScriptGroup2Create(
      (RsContext)con, nameUTF.c_str(), nameUTF.length(),
      (RsContext)con, nameUTF.c_str(), nameUTF.length(),
      cacheDirUTF.c_str(), cacheDirUTF.length(),
      cacheDirUTF.c_str(), cacheDirUTF.length(),
      closures, numClosures);
      closures, numClosures);

exit:

  _env->ReleaseLongArrayElements(closureArray, jClosures, JNI_ABORT);

  return ret;
}
}


static void
static void
@@ -1766,8 +1877,14 @@ nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,


    if (ains != nullptr) {
    if (ains != nullptr) {
        in_len = _env->GetArrayLength(ains);
        in_len = _env->GetArrayLength(ains);
        in_ptr = _env->GetLongArrayElements(ains, nullptr);
        if (in_len > (jint)kMaxNumberKernelArguments) {
            ALOGE("Too many arguments in kernel launch.");
            // TODO (b/20758983): Report back to Java and throw an exception
            return;
        }


        // TODO (b/20760800): Check in_ptr is not null
        in_ptr = _env->GetLongArrayElements(ains, nullptr);
        if (sizeof(RsAllocation) == sizeof(jlong)) {
        if (sizeof(RsAllocation) == sizeof(jlong)) {
            in_allocs = (RsAllocation*)in_ptr;
            in_allocs = (RsAllocation*)in_ptr;


@@ -1775,6 +1892,11 @@ nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
            // Convert from 64-bit jlong types to the native pointer type.
            // Convert from 64-bit jlong types to the native pointer type.


            in_allocs = (RsAllocation*)alloca(in_len * sizeof(RsAllocation));
            in_allocs = (RsAllocation*)alloca(in_len * sizeof(RsAllocation));
            if (in_allocs == nullptr) {
                ALOGE("Failed launching kernel for lack of memory.");
                _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
                return;
            }


            for (int index = in_len; --index >= 0;) {
            for (int index = in_len; --index >= 0;) {
                in_allocs[index] = (RsAllocation)in_ptr[index];
                in_allocs[index] = (RsAllocation)in_ptr[index];