Instead of crashing the VM we will fail the primitive if a type
can not be converted from Smalltalk to C. The code attempts to
free all data allocated for this primitive.

2011-02-04  Holger Hans Peter Freyther  <hol...@freyther.de>

        * libgst/cint.c: Propagate type conversion failures.

2011-02-04  Holger Hans Peter Freyther  <ze...@selfish.org>

        * UnitTest.st: Verify that the primitive are failing.

Signed-off-by: Holger Hans Peter Freyther <ze...@selfish.org>
---
 ChangeLog                    |    4 +++
 libgst/cint.c                |   51 +++++++++++++++++++++++++++++------------
 packages/sockets/ChangeLog   |    4 +++
 packages/sockets/UnitTest.st |   15 ++++++++++++
 4 files changed, 59 insertions(+), 15 deletions(-)


diff --git a/ChangeLog b/ChangeLog
index 1f61455..c32ff6e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2011-02-04  Holger Hans Peter Freyther  <hol...@freyther.de>
 
+	* libgst/cint.c: Propagate type conversion failures.
+
+2011-02-04  Holger Hans Peter Freyther  <hol...@freyther.de>
+
 	* tests/testsuite.at: Add the Sockets test.
 
 2011-02-04  Holger Hans Peter Freyther  <hol...@freyther.de>
diff --git a/libgst/cint.c b/libgst/cint.c
index ec6bc18..d16b153 100644
--- a/libgst/cint.c
+++ b/libgst/cint.c
@@ -7,7 +7,7 @@
 
 /***********************************************************************
  *
- * Copyright 1988,89,90,91,92,94,95,99,2000,2001,2002,2003,2005,2006,2007,2008,2009
+ * Copyright 1988,89,90,91,92,94,95,99,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011
  * Free Software Foundation, Inc.
  * Written by Steve Byrne.
  *
@@ -150,9 +150,10 @@ static void marli (int n);
 static void bad_type (OOP class_oop,
 		      cdata_type cType);
 
-/* Determines the appropriate C mapping for OOP and stores it.  */
-static void push_smalltalk_obj (OOP oop,
-				cdata_type cType);
+/* Determines the appropriate C mapping for OOP and stores it. This
+   returns 1 in case the type could not be converted. */
+static int push_smalltalk_obj (OOP oop,
+			       cdata_type cType);
 
 /* Converts the return type as stored in RESULT to an OOP, based
    on the RETURNTYPEOOP that is stored in the descriptor.  #void is
@@ -852,13 +853,18 @@ _gst_invoke_croutine (OOP cFuncOOP,
   /* Push the arguments */
   for (si = i = 0; i < fixedArgs; i++)
     {
+      int res = 0;
+
       cType = IS_OOP (argTypes[i]) ? CDATA_COBJECT : TO_INT (argTypes[i]);
       if (cType == CDATA_SELF || cType == CDATA_SELF_OOP)
-	push_smalltalk_obj (receiver,
-			    cType == CDATA_SELF ? CDATA_UNKNOWN : CDATA_OOP);
+	res = push_smalltalk_obj (receiver,
+				  cType == CDATA_SELF ? CDATA_UNKNOWN : CDATA_OOP);
       else if (cType != CDATA_VOID)
 	/* Do nothing if it is a void */
-	push_smalltalk_obj (args[si++], cType);
+	res = push_smalltalk_obj (args[si++], cType);
+
+      if (res != 0)
+	goto cleanup;
     }
 
   /* If the previous call was done through the same function descriptor,
@@ -917,6 +923,19 @@ _gst_invoke_croutine (OOP cFuncOOP,
 
   INC_RESTORE_POINTER (incPtr);
   return (oop);
+
+cleanup:
+  /* Attempt to cleanup all pushing of arguments. We have tried to
+     write at si and now need to cleanup up until this point. */
+  for (i = 0, arg = local_arg_vec; i < si; i++, arg++)
+    {
+      if (!arg->oop)
+	continue;
+
+      xfree (arg->u.ptrVal);
+    }
+  INC_RESTORE_POINTER (incPtr);
+  return NULL;
 }
 
 ffi_type *
@@ -1191,7 +1210,7 @@ smalltalk_to_c (OOP oop,
   return NULL;
 }
 
-void
+int
 push_smalltalk_obj (OOP oop,
 		    cdata_type cType)
 {
@@ -1201,12 +1220,13 @@ push_smalltalk_obj (OOP oop,
       if (OOP_INT_CLASS (oop) != _gst_array_class)
 	{
           bad_type (OOP_INT_CLASS (oop), cType);
-          return;
+          return 1;
 	}
 
       cType = (cType == CDATA_VARIADIC) ? CDATA_UNKNOWN : CDATA_OOP;
       for (i = 1; i <= NUM_WORDS (OOP_TO_OBJ (oop)); i++)
-	push_smalltalk_obj (ARRAY_AT (oop, i), cType);
+	if (push_smalltalk_obj (ARRAY_AT (oop, i), cType) != 0)
+	  return 1;
     }
   else
     {
@@ -1216,7 +1236,11 @@ push_smalltalk_obj (OOP oop,
 	INC_ADD_OOP (cp->oop);
       if (type)
 	c_func_cur->types[c_func_cur->arg_idx++] = type;
+      else
+	return 1;
     }
+
+  return 0;
 }
 
 OOP
@@ -1345,8 +1369,6 @@ bad_type (OOP class_oop,
   else
     _gst_errorf ("Attempt to pass an instance of %O as a %s", class_oop,
 	         c_type_name[cType]);
-
-  _gst_show_backtrace (stderr);
 }
 
 
@@ -1381,10 +1403,9 @@ closure_msg_send (ffi_cif* cif, void* result, void** args, void* userdata)
 
   desc = (gst_c_callable) OOP_TO_OBJ (callbackOOP);
   cType = IS_OOP (desc->returnTypeOOP) ? CDATA_COBJECT : TO_INT (desc->returnTypeOOP);
-  if (cType != CDATA_VOID)
+  if (cType != CDATA_VOID && smalltalk_to_c (resultOOP, &cp, cType))
     {
-      smalltalk_to_c (resultOOP, &cp, cType);
-      memcpy (result, &cp.u, sizeof (ffi_arg));
+        memcpy (result, &cp.u, sizeof (ffi_arg));
     }
 }
 
diff --git a/packages/sockets/ChangeLog b/packages/sockets/ChangeLog
index 2cb65f7..69726c8 100644
--- a/packages/sockets/ChangeLog
+++ b/packages/sockets/ChangeLog
@@ -1,5 +1,9 @@
 2011-02-04  Holger Hans Peter Freyther  <ze...@selfish.org>
 
+	* UnitTest.st: Verify that the primitive are failing.
+
+2011-02-04  Holger Hans Peter Freyther  <ze...@selfish.org>
+
 	* package.xml: Add test section.
 	* UnitTest.st: Add SUnit based testcase.
 
diff --git a/packages/sockets/UnitTest.st b/packages/sockets/UnitTest.st
index abd59c2..da19943 100644
--- a/packages/sockets/UnitTest.st
+++ b/packages/sockets/UnitTest.st
@@ -50,4 +50,19 @@ TestCase subclass: SocketTest [
 	datagram := Datagram new.
 	socket nextPut: datagram.
     ]
+
+    testDoNotCrashWithWrongTypes [
+        "The objective is to see if wrong types for a cCallout will
+         make the VM crash or not. It should also check if these calls
+         raise the appropriate exception."
+        | socket impl |
+
+        socket := DatagramSocket new.
+        impl := socket implementation.
+
+        self should: [impl accept: -1 peer: nil addrLen: 0] raise: SystemExceptions.PrimitiveFailed.
+        self should: [impl getPeerName: -1 addr: nil addrLen: 0] raise: SystemExceptions.PrimitiveFailed.
+        self should: [impl getSockName: -1 addr: nil addrLen: 0] raise: SystemExceptions.PrimitiveFailed.
+        self should: [impl receive: -1 buffer: nil size: 0 flags: 0 from: nil size: 0] raise: SystemExceptions.PrimitiveFailed.
+    ]
 ]

_______________________________________________
help-smalltalk mailing list
help-smalltalk@gnu.org
http://lists.gnu.org/mailman/listinfo/help-smalltalk

Reply via email to