[Rprotobuf-commits] r480 - in pkg: . R inst/unitTests man src

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sat Sep 22 01:19:25 CEST 2012


Author: murray
Date: 2012-09-22 01:19:25 +0200 (Sat, 22 Sep 2012)
New Revision: 480

Modified:
   pkg/ChangeLog
   pkg/R/containing_type.R
   pkg/inst/unitTests/runit.FieldDescriptor.R
   pkg/man/containing_type-methods.Rd
   pkg/src/S4_classes.h
Log:
Fix bug causing segfaults when containing_type() is caused because the
return value is never checked and the code attempted to dereference
NULL pointers.  Add documentation and tests showing this working
properly now.



Modified: pkg/ChangeLog
===================================================================
--- pkg/ChangeLog	2012-08-22 06:18:04 UTC (rev 479)
+++ pkg/ChangeLog	2012-09-21 23:19:25 UTC (rev 480)
@@ -1,3 +1,17 @@
+2012-09-21  Murray Stokely  <murray at FreeBSD.org>
+
+	* Fix a bug causing segfaults in containing_type().
+	* R/containing_type.R: Return NULL instead of invalid descriptors
+	when there is no containing type for an object.
+	* src/S4_classes.h: Check for NULL pointers in the contructors for
+	S4_Descriptor and S4_EnumDescriptor as these methods are called on
+	the return value of e.g. containing_type() in the protobuf API
+	without checking the return alue.
+	* man/containing_type-methods.Rd: Add examples section showing
+	cases where there is and is not a containing_type.
+	* inst/unitTests/runit.FieldDescriptor.R
+	(test.FieldDescriptor.class): Add tests for the above.
+
 2012-08-21  Murray Stokely  <murray at FreeBSD.org>
 
 	* src/mutators.cpp: Add better input checking when setting an

Modified: pkg/R/containing_type.R
===================================================================
--- pkg/R/containing_type.R	2012-08-22 06:18:04 UTC (rev 479)
+++ pkg/R/containing_type.R	2012-09-21 23:19:25 UTC (rev 480)
@@ -4,12 +4,26 @@
 } )
 
 setMethod( "containing_type", "Descriptor", function(object){
-	.Call( "Descriptor__containing_type", object at pointer, PACKAGE = "RProtoBuf" )
+	retval <- .Call( "Descriptor__containing_type", object at pointer, PACKAGE = "RProtoBuf" )
+	if (length(retval at type) == 0) {
+		# Descriptors do not always have containing types.
+		# In such cases NULL is better return value than malformed Descriptor.
+		return(NULL)
+	} else {
+                return(retval)
+	}
 } )
 setMethod( "containing_type", "EnumDescriptor", function(object){
-	.Call( "EnumDescriptor__containing_type", object at pointer, PACKAGE = "RProtoBuf" )
+	retval <- .Call( "EnumDescriptor__containing_type", object at pointer, PACKAGE = "RProtoBuf" )
+	if (length(retval at name) == 0) {
+                # If this enum type is nested in a message type, this is that message type.
+                # Otherwise, NULL.
+		return(NULL)
+	} else {
+                return(retval)
+	}
 } )
 setMethod( "containing_type", "FieldDescriptor", function(object){
+        # Never NULL
 	.Call( "FieldDescriptor__containing_type", object at pointer, PACKAGE = "RProtoBuf" )
 } )
-

Modified: pkg/inst/unitTests/runit.FieldDescriptor.R
===================================================================
--- pkg/inst/unitTests/runit.FieldDescriptor.R	2012-08-22 06:18:04 UTC (rev 479)
+++ pkg/inst/unitTests/runit.FieldDescriptor.R	2012-09-21 23:19:25 UTC (rev 480)
@@ -55,4 +55,10 @@
 
   # Return the class of a message field
   checkTrue(inherits(message_type(Person$phone), "Descriptor"))
+
+  # Containing type of a field is the message descriptor
+  checkTrue(inherits(Person$id$containing_type(), "Descriptor"))
+
+  # No containing type for the top-level message descriptor.
+  checkTrue(is.null(Person$containing_type()))
 }

Modified: pkg/man/containing_type-methods.Rd
===================================================================
--- pkg/man/containing_type-methods.Rd	2012-08-22 06:18:04 UTC (rev 479)
+++ pkg/man/containing_type-methods.Rd	2012-09-21 23:19:25 UTC (rev 480)
@@ -11,5 +11,11 @@
 \linkS4class{Descriptor}, \linkS4class{EnumDescriptor}, 
 \linkS4class{FieldDescriptor}
 }
+\examples{
+# Containing type of a field is the message descriptor
+tutorial.Person$id$containing_type()
+
+# No containing type for the top-level message descriptor.
+tutorial.Person$containing_type()
+}
 \keyword{methods}
-

Modified: pkg/src/S4_classes.h
===================================================================
--- pkg/src/S4_classes.h	2012-08-22 06:18:04 UTC (rev 479)
+++ pkg/src/S4_classes.h	2012-09-21 23:19:25 UTC (rev 480)
@@ -54,7 +54,11 @@
 		S4_Descriptor( const GPB::Descriptor* d) : S4( "Descriptor" ){
 			slot( "pointer" ) = Rcpp::XPtr<GPB::Descriptor>( 
 				const_cast<GPB::Descriptor*>(d), false) ;
-			slot( "type" )    = d->full_name() ;
+			if (!d) {
+				slot( "type" ) = Rcpp::StringVector(0) ;
+			} else {
+				slot( "type" ) = d->full_name() ;
+			}
 		}
 		
 		S4_Descriptor( const S4_Descriptor& other) : S4(){
@@ -141,15 +145,18 @@
 		S4_EnumDescriptor( const GPB::EnumDescriptor* d) : S4( "EnumDescriptor" ){
 			slot( "pointer" ) = Rcpp::XPtr<GPB::EnumDescriptor>( 
 				const_cast<GPB::EnumDescriptor*>(d), false) ;
-			slot( "name" )     = d->name() ;
-			slot( "full_name") = d->full_name() ;
-			const GPB::Descriptor *type_desc = d->containing_type() ;
-			if( type_desc ){
-				slot( "type" ) = type_desc->full_name()  ;
-			} else{
-				slot( "type" ) = Rcpp::StringVector(0) ;
+			slot( "type" ) = Rcpp::StringVector(0) ;
+			if (d) {
+				slot( "name" )	   = d->name() ;
+				slot( "full_name") = d->full_name() ;
+				const GPB::Descriptor *type_desc = d->containing_type() ;
+				if( type_desc ){
+					slot( "type" ) = type_desc->full_name()	 ;
+				}
+			} else {
+				slot( "name" )	   = Rcpp::StringVector(0) ;
+				slot( "full_name") = Rcpp::StringVector(0) ;
 			}
-			
 		}
 		
 		S4_EnumDescriptor( const S4_EnumDescriptor& other) : S4(){



More information about the Rprotobuf-commits mailing list