Skip to content

Commit

Permalink
Adding type checking and buffer safety for Java method signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
xevor11 committed Sep 25, 2024
1 parent da1b85d commit 0013016
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 36 deletions.
112 changes: 77 additions & 35 deletions cobc/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -7100,8 +7100,8 @@ output_java_call (struct cb_call *p)
char *last_dot;
char *method_name;
const char *class_name;
char return_type_signature[32];
char method_signature[2048] = "(";
char return_type_signature[COB_MINI_BUFF];
char method_signature[COB_NORMAL_BUFF] = "(";
char* mangled;
struct cb_tree_common *ptr;

Expand All @@ -7122,29 +7122,44 @@ output_java_call (struct cb_call *p)

for (int i = 0; (ptr = ((struct cb_tree_common **)p->args)[i]) != NULL; i++) {
switch(CB_TREE_TAG(ptr)) {
case CB_TAG_INTEGER:
strcat(method_signature, "I");
break;
case CB_TAG_INTEGER: {
struct cb_picture* pic = CB_FIELD(ptr)->pic;
if (pic) {
int n = pic->digits;
if (CB_FIELD(ptr)->usage == CB_USAGE_COMP_5) {
if (n >= 1 && n <= 4) {
strncat(method_signature, "S", COB_NORMAL_BUFF - strlen(method_signature) - 1);
} else if (n >= 5 && n <= 9) {
strncat(method_signature, "I", COB_NORMAL_BUFF - strlen(method_signature) - 1);
} else if (n >= 10 && n <= 18) {
strncat(method_signature, "J", COB_NORMAL_BUFF - strlen(method_signature) - 1);
}
} else if (CB_FIELD(ptr)->usage == CB_USAGE_PACKED || CB_FIELD(ptr)->usage == CB_USAGE_DISPLAY) {
strncat(method_signature, "Ljava/math/BigDecimal;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
}
}
break;
}
case CB_USAGE_FLOAT:
strcat(method_signature, "F");
strncat(method_signature, "F", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_USAGE_DOUBLE:
strcat(method_signature, "D");
strncat(method_signature, "D", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_CLASS_BOOLEAN:
strcat(method_signature, "Z");
strncat(method_signature, "Z", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_TAG_STRING:
strcat(method_signature, "Ljava/lang/String;");
strncat(method_signature, "Ljava/lang/String;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_USAGE_OBJECT:
strcat(method_signature, "Ljava/lang/Object;");
strncat(method_signature, "Ljava/lang/Object;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_TAG_LITERAL:
if(CB_TREE_CATEGORY(ptr) == CB_CATEGORY_NUMERIC) {
strcat(method_signature, "I");
strncat(method_signature, "I", COB_NORMAL_BUFF - strlen(method_signature) - 1);
} else if(CB_TREE_CATEGORY(ptr) == CB_CATEGORY_ALPHANUMERIC) {
strcat(method_signature, "Ljava/lang/String;");
strncat(method_signature, "Ljava/lang/String;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
}
break;
case CB_TAG_LIST:
Expand All @@ -7160,23 +7175,38 @@ output_java_call (struct cb_call *p)
inner_list = (struct cb_tree_common **) list_elements[j];
} else {
switch (CB_TREE_TAG(list_elements[j])) {
case CB_TAG_INTEGER:
strcat(method_signature, "[I");
break;
case CB_TAG_INTEGER: {
struct cb_picture* pic = CB_FIELD(list_elements[j])->pic;
if (pic) {
int n = pic->digits;
if (CB_FIELD(list_elements[j])->usage == CB_USAGE_COMP_5) {
if (n >= 1 && n <= 4) {
strncat(method_signature, "[S", COB_NORMAL_BUFF - strlen(method_signature) - 1);
} else if (n >= 5 && n <= 9) {
strncat(method_signature, "[I", COB_NORMAL_BUFF - strlen(method_signature) - 1);
} else if (n >= 10 && n <= 18) {
strncat(method_signature, "[J", COB_NORMAL_BUFF - strlen(method_signature) - 1);
}
} else if (CB_FIELD(list_elements[j])->usage == CB_USAGE_PACKED || CB_FIELD(list_elements[j])->usage == CB_USAGE_DISPLAY) {
strncat(method_signature, "[Ljava/math/BigDecimal;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
}
}
break;
}
case CB_USAGE_FLOAT:
strcat(method_signature, "[F");
strncat(method_signature, "[F", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_USAGE_DOUBLE:
strcat(method_signature, "[D");
strncat(method_signature, "[D", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_CLASS_BOOLEAN:
strcat(method_signature, "[Z");
strncat(method_signature, "[Z", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_TAG_STRING:
strcat(method_signature, "[Ljava/lang/String;");
strncat(method_signature, "[Ljava/lang/String;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
case CB_USAGE_OBJECT:
strcat(method_signature, "[Ljava/lang/Object;");
strncat(method_signature, "[Ljava/lang/Object;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
break;
default:
cobc_err_msg(_("Unsupported array element type in Java method call"));
Expand All @@ -7186,46 +7216,58 @@ output_java_call (struct cb_call *p)
}
list_elements = inner_list;
}

if (array_dimension > 2) {
cobc_err_msg(_("Unsupported array dimension: %d"), array_dimension);
COBC_ABORT();
}
}
break;
default:
cobc_err_msg(_("Unsupported argument type in Java method call"));
COBC_ABORT();
}
}

if (p->call_returning == NULL) {
strcat(method_signature, ")V");
strncat(method_signature, ")V", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "void");
} else {
switch(CB_TREE_TAG(p->call_returning)) {
case CB_TAG_INTEGER:
strcat(method_signature, ")I");
strcpy(return_type_signature, "jint");
case CB_TAG_INTEGER: {
struct cb_picture* pic = CB_FIELD(p->call_returning)->pic;
if (pic) {
int n = pic->digits;
if (CB_FIELD(p->call_returning)->usage == CB_USAGE_COMP_5) {
if (n >= 1 && n <= 4) {
strncat(method_signature, ")S", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "jshort");
} else if (n >= 5 && n <= 9) {
strncat(method_signature, ")I", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "jint");
} else if (n >= 10 && n <= 18) {
strncat(method_signature, ")J", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "jlong");
}
} else if (CB_FIELD(p->call_returning)->usage == CB_USAGE_PACKED || CB_FIELD(p->call_returning)->usage == CB_USAGE_DISPLAY) {
strncat(method_signature, ")Ljava/math/BigDecimal;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "jobject");
}
}
break;
}
case CB_TAG_STRING:
strcat(method_signature, ")Ljava/lang/String;");
strncat(method_signature, ")Ljava/lang/String;", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "jstring");
break;
case CB_USAGE_FLOAT:
strcat(method_signature, ")F");
strncat(method_signature, ")F", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "jfloat");
break;
case CB_USAGE_DOUBLE:
strcat(method_signature, ")D");
strncat(method_signature, ")D", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "jdouble");
break;
case CB_CLASS_BOOLEAN:
strcat(method_signature, ")Z");
strncat(method_signature, ")Z", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "jboolean");
break;
default:
strcat(method_signature, ")V");
strncat(method_signature, ")V", COB_NORMAL_BUFF - strlen(method_signature) - 1);
strcpy(return_type_signature, "void");
break;
}
Expand Down
45 changes: 44 additions & 1 deletion cobc/typeck.c
Original file line number Diff line number Diff line change
Expand Up @@ -3985,6 +3985,50 @@ cb_check_conformance (cb_tree prog_ref, cb_tree using_list,
}
}

/* Additional conformance checks for Java method calls */
for (l = using_list; l; l = CB_CHAIN(l)) {
struct cb_tree_common *arg = (struct cb_tree_common *)CB_VALUE(l);

/* Ensure only field identifiers are used */
if (CB_TREE_TAG(arg) == CB_TAG_LITERAL || CB_TREE_TAG(arg) == CB_TAG_FUNCALL) {
cobc_err_msg(_("Invalid argument type in Java method call. Only field identifiers are allowed."));
COBC_ABORT();
}

/* Check for unsupported array element types and dimensions */
if (CB_TREE_TAG(arg) == CB_TAG_LIST) {
int array_dimension = 1;
struct cb_tree_common **list_elements = (struct cb_tree_common **)arg;
while (list_elements != NULL) {
struct cb_tree_common **inner_list = NULL;
for (int j = 0; list_elements[j] != NULL; j++) {
if (CB_TREE_TAG(list_elements[j]) == CB_TAG_LIST) {
array_dimension++;
inner_list = (struct cb_tree_common **)list_elements[j];
} else {
switch (CB_TREE_TAG(list_elements[j])) {
case CB_TAG_INTEGER:
case CB_USAGE_FLOAT:
case CB_USAGE_DOUBLE:
case CB_CLASS_BOOLEAN:
case CB_TAG_STRING:
case CB_USAGE_OBJECT:
break;
default:
cobc_err_msg(_("Unsupported array element type in Java method call"));
COBC_ABORT();
}
}
}
list_elements = inner_list;
}
if (array_dimension > 2) {
cobc_err_msg(_("Unsupported array dimension: %d"), array_dimension);
COBC_ABORT();
}
}
}

/* Check RETURNING item. */

if (returning && program->returning) {
Expand Down Expand Up @@ -15478,7 +15522,6 @@ cb_emit_xml_parse (cb_tree data, cb_tree proc,
#endif
ref = cb_ref (data);
if (CB_FIELD_P (ref)) {
struct cb_field * field = CB_FIELD (ref);
/* type checks here */
cb_emit (cb_build_xml_parse (data, proc, returning_national,
encoding, validation));
Expand Down

0 comments on commit 0013016

Please sign in to comment.