-
Bug
-
Resolution: Cannot Reproduce
-
P3
-
8u202
-
x86_64
-
linux
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
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