ports/152882: comms/rxtx page fault/crash

Bob Frazier bobf at mrp3.com
Tue Dec 7 06:10:11 UTC 2010


>Number:         152882
>Category:       ports
>Synopsis:       comms/rxtx page fault/crash
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Dec 07 06:10:10 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Bob Frazier
>Release:        7.3-STABLE
>Organization:
S.F.T. Inc.
>Environment:
FreeBSD BSDSilver.SFT.local 7.3-STABLE FreeBSD 7.3-STABLE #12: Tue Nov 23 20:43:00 PST 2010     root at BSDSilver.SFT.local:/usr/obj/usr/src/sys/GENERIC  amd64
>Description:
A software coding error in comms/rxtx causes a page fault when attempting to access a java variable by reference.  The error is due to incorrect use of GetIntField instead of GetObjectField.  A set of patches have been included that appear to correct the problem when placed into the 'files' directory of the port prior to building the port.


>How-To-Repeat:
using a java COMM application (such as devel/arduino) attempt to do serial I/O on a comm port.  In my case it was a USB comm port '/dev/ttyU0'.  Simply attempting a transfer is enough to cause the crash.

>Fix:
the three files src/SerialImp.c src/SerialImp.cpp and src/SerialImp.h must be patched using the attached files (or similar).

Patch attached with submission follows:

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	rxtx
#	rxtx/files
#	rxtx/files/patch-SerialImp.h
#	rxtx/files/patch-SerialImp.cpp
#	rxtx/files/patch-SerialImp.c
#
echo c - rxtx
mkdir -p rxtx > /dev/null 2>&1
echo c - rxtx/files
mkdir -p rxtx/files > /dev/null 2>&1
echo x - rxtx/files/patch-SerialImp.h
sed 's/^X//' >rxtx/files/patch-SerialImp.h << '375c7bbc64083cac744fa1f2532d67e4'
X--- src/SerialImp.h.orig	2005-07-05 10:47:21.000000000 -0700
X+++ src/SerialImp.h	2010-12-05 21:47:42.000000000 -0800
X@@ -438,8 +438,13 @@
X void system_does_not_unlock( const char *, int );
X int check_group_uucp();
X int check_lock_pid( const char *, int );
X int printj(JNIEnv *env, wchar_t *fmt, ...);
X 
X+// BBB added
X+void deref_java_object( JNIEnv *env, jobject jobj );
X+void * get_java_varP( JNIEnv *env, jobject jobj, char *id, char *type );
X+
X+
X #define UNEXPECTED_LOCK_FILE "RXTX Error:  Unexpected lock file: %s\n Please report to the RXTX developers\n"
X #define LINUX_KERNEL_VERSION_ERROR "\n\n\nRXTX WARNING:  This library was compiled to run with OS release %s and you are currently running OS release %s.  In some cases this can be a problem.  Try recompiling RXTX if you notice strange behavior.  If you just compiled RXTX make sure /usr/include/linux is a symbolic link to the include files that came with the kernel source and not an older copy.\n\n\npress enter to continue\n"
X #define UUCP_ERROR "\n\n\nRXTX WARNING:  This library requires the user running applications to be in\ngroup uucp.  Please consult the INSTALL documentation.  More information is\navaiable under the topic 'How can I use Lock Files with rxtx?'\n" 
375c7bbc64083cac744fa1f2532d67e4
echo x - rxtx/files/patch-SerialImp.cpp
sed 's/^X//' >rxtx/files/patch-SerialImp.cpp << '29e44cd8508495ee769fe53c84b57552'
X--- src/SerialImp.cpp.orig	2004-10-12 01:59:27.000000000 -0700
X+++ src/SerialImp.cpp	2010-12-06 21:48:20.000000000 -0800
X@@ -1736,10 +1736,50 @@
X 		report("invalid file descriptor\n");
X #endif
X 	return result;
X }
X 
X+void deref_java_object( JNIEnv *env, jobject jobj )
X+{
X+  jclass jclazz = env->GetObjectClass( env, jobj );
X+  env->DeleteLocalRef( env, jclazz );
X+}
X+
X+void * get_java_varP( JNIEnv *env, jobject jobj, char *id, char *type )
X+{
X+
X+
X+   ////////////////// Open Log File /////////////////////
X+   fp = fopen("RXTXOut.log", "a");
X+   fprintf(fp, "Brian is inside get_java_varP\n"); // !!!
X+   fclose(fp);
X+   ////////////////// Close Log File ////////////////////
X+
X+	void * result = 0;
X+	//jclass jclazz = (*env)->GetObjectClass( env, jobj );
X+	jclass jclazz = env->GetObjectClass( jobj ); // !!!
X+	//jfieldID jfd = (*env)->GetFieldID( env, jclazz, id, type );
X+    jfieldID jfd = env->GetFieldID( jclazz, id, type ); // !!!
X+    
X+	if( !jfd ) {
X+		//(*env)->ExceptionDescribe( env );
X+		env->ExceptionDescribe(); // !!!
X+		//(*env)->ExceptionClear( env );
X+		env->ExceptionClear(); // !!!
X+		return result;
X+	}
X+	//result = (int)( (*env)->GetIntField( env, jobj, jfd ) );
X+	result = (void *)( env->GetIntField( jobj, jfd ) ); // !!!
X+/* ct7 & gel * Added DeleteLocalRef */
X+	//(*env)->DeleteLocalRef( env, jclazz );
X+//	env->DeleteLocalRef( jclazz ); // !!!
X+#ifdef DEBUG
X+	if(!strncmp("fd",id,2) && result == 0)
X+		report("invalid file descriptor\n");
X+#endif
X+	return result;
X+}
X /*----------------------------------------------------------
X throw_java_exception
X 
X    accept:      env (keyhole to java)
X                 *exc (exception class name)
29e44cd8508495ee769fe53c84b57552
echo x - rxtx/files/patch-SerialImp.c
sed 's/^X//' >rxtx/files/patch-SerialImp.c << '5ac5e6c673ede56f265b5168ecba1897'
X--- src/SerialImp.c.orig	2006-01-29 14:19:04.000000000 -0800
X+++ src/SerialImp.c	2010-12-05 22:41:39.000000000 -0800
X@@ -1528,11 +1528,11 @@
X ----------------------------------------------------------*/
X JNIEXPORT jboolean JNICALL RXTXPort(nativeDrain)( JNIEnv *env,
X 	jobject jobj, jboolean interrupted )
X {
X 	int fd = get_java_var( env, jobj,"fd","I" );
X-	struct event_info_struct *eis = ( struct event_info_struct * ) get_java_var( env, jobj, "eis", "J" );
X+	struct event_info_struct *eis = ( struct event_info_struct * ) get_java_varP( env, jobj, "eis", "J" ); // does not deref
X 	int result, count=0;
X 
X 	char message[80];
X 
X 	ENTER( "SerialImp.c:drain()" );
X@@ -1545,16 +1545,21 @@
X 
X 	sprintf( message, "RXTXPort:drain() returns: %i\n", result ); 
X 	report_verbose( message );
X #if defined(__sun__)
X 	/* FIXME: No time to test on all OS's for production */
X+        deref_java_object(env, jobj);
X 	return( JNI_TRUE );
X #endif /* __sun__ */
X 	LEAVE( "RXTXPort:drain()" );
X 	if( result ) throw_java_exception( env, IO_EXCEPTION, "nativeDrain",
X 		strerror( errno ) );
X-	if( interrupted ) return( JNI_FALSE );
X+	if( interrupted )
X+        {
X+          deref_java_object(env, jobj);
X+          return( JNI_FALSE );
X+        }
X #if !defined(TIOCSERGETLSR) && !defined(WIN32)
X 	if( eis && eis->writing )
X 	{
X 		eis->writing=JNI_FALSE;
X 		eis->output_buffer_empty_flag = 0;
X@@ -1565,10 +1570,12 @@
X                 struct event_info_struct myeis =
X 			build_threadsafe_eis( env, &jobj, eis );
X 		send_event( &myeis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
X 	}
X 	report_time_end( );
X+
X+        deref_java_object(env, jobj);
X 	return( JNI_FALSE );
X }
X 
X /*----------------------------------------------------------
X RXTXPort.sendBreak
X@@ -2937,11 +2944,11 @@
X 	struct timeval tv, *tvP;
X 	fd_set rset;
X 	/* TRENT */
X 	int flag, count = 0;
X 	struct event_info_struct *eis = ( struct event_info_struct * )
X-		get_java_var( env, *jobj,"eis","J" );
X+		get_java_varP( env, *jobj,"eis","J" ); // does not dereference object (pointer remains valid)
X 	
X 	report_time_start();
X 	flag = eis->eventflags[SPE_DATA_AVAILABLE];
X 	eis->eventflags[SPE_DATA_AVAILABLE] = 0;
X /*
X@@ -2957,10 +2964,11 @@
X 		if (timeout >= 0) {
X 			now = GetTickCount();
X 			if ( now-start >= timeout )
X 			{
X 				eis->eventflags[SPE_DATA_AVAILABLE] = flag;
X+                                deref_java_object( env, *jobj );
X 				return bytes;
X 			}
X 		}
X 
X 		FD_ZERO(&rset);
X@@ -2983,22 +2991,25 @@
X #endif /* WIN32 */
X 		if (ret == -1){
X 			report( "read_byte_array: select returned -1\n" );
X 			LEAVE( "read_byte_array" );
X 			eis->eventflags[SPE_DATA_AVAILABLE] = flag;
X+                        deref_java_object( env, *jobj );
X 			return -1;
X 		}
X 		else if (ret > 0)
X 		{
X 			if ((ret = READ( fd, buffer + bytes, left )) < 0 ){
X 				if (errno != EINTR && errno != EAGAIN){
X 					report( "read_byte_array: read returned -1\n" );
X 					LEAVE( "read_byte_array" );
X 					eis->eventflags[SPE_DATA_AVAILABLE] = flag;
X+                                        deref_java_object( env, *jobj );
X 					return -1;
X 				}
X 				eis->eventflags[SPE_DATA_AVAILABLE] = flag;
X+                                deref_java_object( env, *jobj );
X 				return -1;
X 			}
X 			else if ( ret ) {
X 				bytes += ret;
X 				left -= ret;
X@@ -3031,10 +3042,12 @@
X 	report( msg );
X 	LEAVE( "read_byte_array" );
X 	report_time_end();
X */
X 	eis->eventflags[SPE_DATA_AVAILABLE] = flag;
X+
X+        deref_java_object( env, *jobj );
X 	return bytes;
X }
X 
X #ifdef asdf
X int read_byte_array(	JNIEnv *env,
X@@ -4898,10 +4911,43 @@
X 	LEAVE( "get_java_var" );
X */
X 	return result;
X }
X 
X+void deref_java_object( JNIEnv *env, jobject jobj )
X+{
X+  jclass jclazz = (*env)->GetObjectClass( env, jobj );
X+  (*env)->DeleteLocalRef( env, jclazz );
X+}
X+
X+void * get_java_varP( JNIEnv *env, jobject jobj, char *id, char *type )
X+{
X+	void * result = 0;
X+	jclass jclazz = (*env)->GetObjectClass( env, jobj );
X+	jfieldID jfd = (*env)->GetFieldID( env, jclazz, id, type );
X+
X+/*
X+	ENTER( "get_java_var" );
X+*/
X+	if( !jfd ) {
X+		(*env)->ExceptionDescribe( env );
X+		(*env)->ExceptionClear( env );
X+		(*env)->DeleteLocalRef( env, jclazz );
X+		LEAVE( "get_java_var" );
X+		return result;
X+	}
X+	result = (void *)( (*env)->GetObjectField( env, jobj, jfd ) );
X+/* ct7 & gel * Added DeleteLocalRef */
X+//	(*env)->DeleteLocalRef( env, jclazz );
X+	if(!strncmp( "fd",id,2) && result == 0)
X+		report_error( "get_java_var: invalid file descriptor\n" );
X+/*
X+	LEAVE( "get_java_var" );
X+*/
X+	return result;
X+}
X+
X /*----------------------------------------------------------
X throw_java_exception
X 
X    accept:      env (keyhole to java)
X                 *exc (exception class name)
5ac5e6c673ede56f265b5168ecba1897
exit



>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list