Browse Source

Prevent subclassing of core classes.

Marco Bambini 8 years ago
parent
commit
e84dce1282

+ 9 - 0
src/compiler/gravity_semacheck2.c

@@ -10,6 +10,7 @@
 #include "gravity_semacheck2.h"
 #include "gravity_semacheck2.h"
 #include "gravity_compiler.h"
 #include "gravity_compiler.h"
 #include "gravity_visitor.h"
 #include "gravity_visitor.h"
+#include "gravity_core.h"
 
 
 struct semacheck_t {
 struct semacheck_t {
 	gnode_r			*declarations;		// declarations stack
 	gnode_r			*declarations;		// declarations stack
@@ -779,6 +780,14 @@ static void visit_class_decl (gvisitor_t *self, gnode_class_decl_t *node) {
 	// check superclass
 	// check superclass
 	if (node->superclass) {
 	if (node->superclass) {
 		gnode_identifier_expr_t *id = (gnode_identifier_expr_t *)node->superclass;
 		gnode_identifier_expr_t *id = (gnode_identifier_expr_t *)node->superclass;
+        
+        // sanity check
+        if (gravity_core_class_from_name(id->value)) {
+            REPORT_ERROR(id, "Unable to subclass built-in core class %s.", id->value);
+            return;
+        }
+        
+        // lookup super node
 		gnode_t *target = lookup_symtable_id(self, id, true);
 		gnode_t *target = lookup_symtable_id(self, id, true);
 		if (!target) REPORT_ERROR(id, "Unable to find superclass %s for class %s.", id->value, node->identifier);
 		if (!target) REPORT_ERROR(id, "Unable to find superclass %s for class %s.", id->value, node->identifier);
 		node->superclass = target;
 		node->superclass = target;

+ 22 - 0
src/runtime/gravity_core.c

@@ -2494,6 +2494,28 @@ void gravity_core_register (gravity_vm *vm) {
 	gravity_vm_setvalue(vm, GRAVITY_CLASS_SYSTEM_NAME, VALUE_FROM_OBJECT(gravity_class_system));
 	gravity_vm_setvalue(vm, GRAVITY_CLASS_SYSTEM_NAME, VALUE_FROM_OBJECT(gravity_class_system));
 }
 }
 
 
+gravity_class_t *gravity_core_class_from_name (const char *name) {
+    if (name) {
+        if (string_cmp(name, GRAVITY_CLASS_OBJECT_NAME) == 0) return gravity_class_object;
+        if (string_cmp(name, GRAVITY_CLASS_CLASS_NAME) == 0) return gravity_class_class;
+        if (string_cmp(name, GRAVITY_CLASS_BOOL_NAME) == 0) return gravity_class_bool;
+        if (string_cmp(name, GRAVITY_CLASS_NULL_NAME) == 0) return gravity_class_null;
+        if (string_cmp(name, GRAVITY_CLASS_INT_NAME) == 0) return gravity_class_int;
+        if (string_cmp(name, GRAVITY_CLASS_FLOAT_NAME) == 0) return gravity_class_float;
+        if (string_cmp(name, GRAVITY_CLASS_FUNCTION_NAME) == 0) return gravity_class_function;
+        if (string_cmp(name, GRAVITY_CLASS_CLOSURE_NAME) == 0) return gravity_class_closure;
+        if (string_cmp(name, GRAVITY_CLASS_FIBER_NAME) == 0) return gravity_class_fiber;
+        if (string_cmp(name, GRAVITY_CLASS_STRING_NAME) == 0) return gravity_class_string;
+        if (string_cmp(name, GRAVITY_CLASS_INSTANCE_NAME) == 0) return gravity_class_instance;
+        if (string_cmp(name, GRAVITY_CLASS_LIST_NAME) == 0) return gravity_class_list;
+        if (string_cmp(name, GRAVITY_CLASS_MAP_NAME) == 0) return gravity_class_map;
+        if (string_cmp(name, GRAVITY_CLASS_RANGE_NAME) == 0) return gravity_class_range;
+        if (string_cmp(name, GRAVITY_CLASS_UPVALUE_NAME) == 0) return gravity_class_upvalue;
+        if (string_cmp(name, GRAVITY_CLASS_SYSTEM_NAME) == 0) return gravity_class_system;
+    }
+    return NULL;
+}
+
 bool gravity_iscore_class (gravity_class_t *c) {
 bool gravity_iscore_class (gravity_class_t *c) {
 	// first check if it is a class
 	// first check if it is a class
 	if ((c == gravity_class_object) || (c == gravity_class_class) || (c == gravity_class_bool) ||
 	if ((c == gravity_class_object) || (c == gravity_class_class) || (c == gravity_class_bool) ||

+ 1 - 0
src/runtime/gravity_core.h

@@ -20,6 +20,7 @@ GRAVITY_API void gravity_core_register (gravity_vm *vm);
 GRAVITY_API bool gravity_iscore_class (gravity_class_t *c);
 GRAVITY_API bool gravity_iscore_class (gravity_class_t *c);
 GRAVITY_API void gravity_core_free (void);
 GRAVITY_API void gravity_core_free (void);
 GRAVITY_API uint32_t gravity_core_identifiers (const char ***id);
 GRAVITY_API uint32_t gravity_core_identifiers (const char ***id);
+GRAVITY_API gravity_class_t *gravity_core_class_from_name (const char *name);
 
 
 // conversion functions
 // conversion functions
 gravity_value_t convert_value2int (gravity_vm *vm, gravity_value_t v);
 gravity_value_t convert_value2int (gravity_vm *vm, gravity_value_t v);

+ 42 - 0
test/fuzzy/issue149.gravity

@@ -0,0 +1,42 @@
+#unittest {
+	name: "Test classes declaration with both static and non static members.";
+	error: NONE;
+};
+
+// class declarations
+class bar {
+	// class var
+	static var a1 = 10;
+	static var a2 = 20;
+	
+	// class const
+	static var b1 = 100;
+	static var b2 = 200;
+	
+	// instance var
+	var c1 = 1000;
+	var c2 = 2000;// instance const
+	const d1 = 10000;
+	const d2 = 20000;
+	
+	static func f1() {
+		return a1+a2+b1+b2;
+	}
+	
+	func f2() {
+		return c1+c2+d1+d2;
+	}
+}
+
+class foo:Int {
+	var e1 = 10;
+	var e2 = 20;
+	
+	func init() {
+		e1 = 100;
+	}
+}
+
+func main() {
+	return;
+}