Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8222324

Crash in JNI's GetDoubleArrayRegion() due to invalid memcpy

    Details

    • Subcomponent:
    • CPU:
      x86_64
    • OS:
      linux

      Description

      ADDITIONAL SYSTEM INFORMATION :
      OS: Ubuntu 16
      # JRE version: Java(TM) SE Runtime Environment (8.0_202-b08) (build 1.8.0_202-b08)
      # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.202-b08 mixed mode linux-amd64 compressed oops)


      A DESCRIPTION OF THE PROBLEM :
      Calling GetDoubleArrayRegion() with a requested length larger than INT_MAX / 8 causes a crash caused by an invalid call to memcpy.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      On a Linux 64 bit machine, do

      1. Save attached files (Makefile, HelloJNI.java, HelloJNI.c)
      2. Set JAVA_HOME
      3. Run 'make'


      ACTUAL -
      javac -h . HelloJNI.java
      gcc -fPIC -I/home/luce/nfshome/tmp/jdk1.8.0_202/include -I/home/luce/nfshome/tmp/jdk1.8.0_202/include/linux -shared -o libhello.so HelloJNI.c
      java -Djava.library.path=. HelloJNI
      Got an array of lenth 268435456
      Allocating buffer for copy
      Getting copy of the input array
      #
      # A fatal error has been detected by the Java Runtime Environment:
      #
      # SIGSEGV (0xb) at pc=0x00007fedb7d186d3, pid=17486, tid=0x00007fedb889e700
      #
      # JRE version: Java(TM) SE Runtime Environment (8.0_202-b08) (build 1.8.0_202-b08)
      # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.202-b08 mixed mode linux-amd64 compressed oops)
      # Problematic frame:
      # C [libc.so.6+0xbb6d3]
      #
      # Core dump written. Default location: /nfs/home/luce/tmp/jnitest/core or core.17486
      #
      # An error report file with more information is saved as:
      # /nfs/home/luce/tmp/jnitest/hs_err_pid17486.log


      ---------- BEGIN SOURCE ----------
      Makefile:
      all:
              javac -h . HelloJNI.java
              gcc -fPIC -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux -shared -o libhello.so HelloJNI.c
              java -Djava.library.path=. HelloJNI

      HelloJNI.java:
      public class HelloJNI { // Save as HelloJNI.java
         static {
            System.loadLibrary("hello"); // Load native library hello.dll (Windows) or libhello.so (Unixes)
                                         // at runtime
                                         // This library contains a native method called sayHello()
         }

         public double[] numbers;
       
         // Declare an instance native method sayHello() which receives no parameter and returns void
         public native double computeSum(double[] arr);

         public HelloJNI() {
             // This is small enough to not trigger the integer overflow
             //final int N = 268435455;
             final int N = 268435456;
             numbers = new double[N];

             for (int k = 0; k < numbers.length; k++) {
                 numbers[k] = 1.0 / (k + 1.0);
             }

         }
       
         // Test Driver
         public static void main(String[] args) {
            HelloJNI obj = new HelloJNI();
            double hsum = obj.computeSum(obj.numbers);

            System.out.println("Harmonic sum is " + hsum);
         }
      }

      HelloJNI.c:
      #include <jni.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include "HelloJNI.h"
       
      JNIEXPORT jdouble JNICALL Java_HelloJNI_computeSum(
          JNIEnv *env,
          jobject obj,
          jdoubleArray arr)
      {
         double *buffer = NULL;
         jdouble retval = 0.0;
         jsize len = (*env)->GetArrayLength(env, arr);
         int k;

         printf("Got an array of lenth %d\n", len);
         printf("Allocating buffer for copy\n");
         buffer = malloc(sizeof(double) * len);

         printf("Getting copy of the input array\n");
         (*env)->GetDoubleArrayRegion(env, arr, 0, len, buffer);

         printf("Computing sum\n");
         for (k = 0; k < len; k++) {
           retval += buffer[k];
         }

         if (buffer != NULL) {
           printf("Decallocating buffer\n");
           free(buffer);
         } else {
           printf("No buffer to deallocate\n");
         }

         return retval;
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Retrieve array regions from GetDoubleArrayRegion in chunks smaller than INT_MAX/8.

      FREQUENCY : always


        Attachments

          Activity

            People

            • Assignee:
              fmatte Fairoz Matte
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated: