You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-commits@axis.apache.org by ro...@apache.org on 2026/01/25 04:14:04 UTC
(axis-axis2-c-core) 02/05: Fix unsigned integer type handling in code generator (AXIS2C-1492)
This is an automated email from the ASF dual-hosted git repository.
robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-c-core.git
commit 80ec82f0ce9a1a908f7defe8f7777977fb9d1b5f
Author: Robert Lazarski <ro...@gmail.com>
AuthorDate: Sat Jan 24 14:36:03 2026 -1000
Fix unsigned integer type handling in code generator (AXIS2C-1492)
The issue: xsd:unsignedInt values above 2147483647 (INT_MAX) were
incorrectly truncated because the generated code used atoi() which
returns signed int. Values like 3000000000 would overflow to negative
numbers (-1294967296).
The fix adds proper XSD integer type detection and C type mapping:
Type detection helpers:
- is_unsigned_integer_type(): Detects unsignedInt, unsignedLong,
unsignedShort, unsignedByte, positiveInteger, nonNegativeInteger
- is_64bit_integer_type(): Detects long, unsignedLong, integer types
- is_integer_type(): Detects all integer types (for free function)
C type mapping:
- xsd:unsignedInt -> unsigned int
- xsd:unsignedLong -> uint64_t
- xsd:unsignedShort -> unsigned int
- xsd:unsignedByte -> unsigned int
- xsd:positiveInteger -> uint64_t
- xsd:nonNegativeInteger -> uint64_t
Conversion functions:
- Unsigned 32-bit types: strtoul(text_value, NULL, 10)
- Unsigned 64-bit types: strtoull(text_value, NULL, 10)
- Signed types: atoi() for 32-bit, strtoll() for 64-bit
Format specifiers:
- Unsigned 32-bit: %u
- Unsigned 64-bit: %llu
- Signed 32-bit: %d
- Signed 64-bit: %lld
Also fixes the _free function to not call AXIS2_FREE on primitive
integer types (they're stack values in the struct, not pointers).
Co-Authored-By: Claude Opus 4.5 <no...@anthropic.com>
---
tools/codegen/native/src/stub_generator.c | 184 +++++++--
tools/codegen/native/test/Makefile.am | 1 +
.../native/test/include/adb_test_framework.h | 11 +
tools/codegen/native/test/src/adb_test_framework.c | 1 +
.../test/src/test_axis2c_1492_unsigned_int.c | 429 +++++++++++++++++++++
5 files changed, 604 insertions(+), 22 deletions(-)
diff --git a/tools/codegen/native/src/stub_generator.c b/tools/codegen/native/src/stub_generator.c
index ad34e107a..b5b693f14 100644
--- a/tools/codegen/native/src/stub_generator.c
+++ b/tools/codegen/native/src/stub_generator.c
@@ -148,6 +148,129 @@ wsdl2c_sanitize_c_identifier(const axutil_env_t *env, const axis2_char_t *wsdl_n
return result;
}
+/* AXIS2C-1492 FIX: XSD integer type detection and C type mapping
+ *
+ * XSD defines several integer types with different ranges:
+ * - Signed: byte, short, int, long, integer (arbitrary precision)
+ * - Unsigned: unsignedByte, unsignedShort, unsignedInt, unsignedLong,
+ * positiveInteger, nonNegativeInteger
+ *
+ * This fix ensures proper C type mapping and conversion functions:
+ * - Unsigned types use unsigned int/uint64_t and strtoul()/strtoull()
+ * - Signed types use int/int64_t and atoi()/strtol()/strtoll()
+ */
+
+/* Check if XSD type is an unsigned integer type */
+axis2_bool_t
+is_unsigned_integer_type(const axis2_char_t *xsd_type)
+{
+ if (!xsd_type) {
+ return AXIS2_FALSE;
+ }
+ /* XSD unsigned integer types */
+ if (strstr(xsd_type, "unsignedInt") ||
+ strstr(xsd_type, "unsignedLong") ||
+ strstr(xsd_type, "unsignedShort") ||
+ strstr(xsd_type, "unsignedByte") ||
+ strstr(xsd_type, "positiveInteger") ||
+ strstr(xsd_type, "nonNegativeInteger")) {
+ return AXIS2_TRUE;
+ }
+ return AXIS2_FALSE;
+}
+
+/* Check if XSD type is a 64-bit integer type (long) */
+axis2_bool_t
+is_64bit_integer_type(const axis2_char_t *xsd_type)
+{
+ if (!xsd_type) {
+ return AXIS2_FALSE;
+ }
+ /* XSD long types (signed and unsigned) */
+ if (strstr(xsd_type, "Long") || strstr(xsd_type, "long") ||
+ strstr(xsd_type, "integer") || strstr(xsd_type, "Integer")) {
+ /* "integer" in XSD is arbitrary precision, map to 64-bit */
+ /* But exclude unsignedInt which contains "int" */
+ if (strstr(xsd_type, "unsignedInt") && !strstr(xsd_type, "unsignedInteg")) {
+ return AXIS2_FALSE;
+ }
+ return AXIS2_TRUE;
+ }
+ return AXIS2_FALSE;
+}
+
+/* Check if XSD type is any integer type (signed or unsigned) */
+axis2_bool_t
+is_integer_type(const axis2_char_t *xsd_type)
+{
+ if (!xsd_type) {
+ return AXIS2_FALSE;
+ }
+ if (strstr(xsd_type, "int") || strstr(xsd_type, "Int") ||
+ strstr(xsd_type, "long") || strstr(xsd_type, "Long") ||
+ strstr(xsd_type, "short") || strstr(xsd_type, "Short") ||
+ strstr(xsd_type, "byte") || strstr(xsd_type, "Byte") ||
+ strstr(xsd_type, "integer") || strstr(xsd_type, "Integer")) {
+ return AXIS2_TRUE;
+ }
+ return AXIS2_FALSE;
+}
+
+/* Get the C type string for an XSD integer type */
+const char*
+get_c_integer_type(const axis2_char_t *xsd_type)
+{
+ if (!xsd_type) {
+ return "int";
+ }
+
+ axis2_bool_t is_unsigned = is_unsigned_integer_type(xsd_type);
+ axis2_bool_t is_64bit = is_64bit_integer_type(xsd_type);
+
+ if (is_64bit) {
+ return is_unsigned ? "uint64_t" : "int64_t";
+ } else {
+ return is_unsigned ? "unsigned int" : "int";
+ }
+}
+
+/* Get the conversion function for deserializing an XSD integer type */
+const char*
+get_integer_deserialize_func(const axis2_char_t *xsd_type)
+{
+ if (!xsd_type) {
+ return "atoi";
+ }
+
+ axis2_bool_t is_unsigned = is_unsigned_integer_type(xsd_type);
+ axis2_bool_t is_64bit = is_64bit_integer_type(xsd_type);
+
+ if (is_64bit) {
+ return is_unsigned ? "strtoull(text_value, NULL, 10)" : "strtoll(text_value, NULL, 10)";
+ } else {
+ return is_unsigned ? "strtoul(text_value, NULL, 10)" : "atoi(text_value)";
+ }
+}
+
+/* Get the printf format specifier for an XSD integer type */
+const char*
+get_integer_format_specifier(const axis2_char_t *xsd_type)
+{
+ if (!xsd_type) {
+ return "%d";
+ }
+
+ axis2_bool_t is_unsigned = is_unsigned_integer_type(xsd_type);
+ axis2_bool_t is_64bit = is_64bit_integer_type(xsd_type);
+
+ if (is_64bit) {
+ /* Use PRIu64/PRId64 macros from inttypes.h, but for simplicity use %llu/%lld */
+ return is_unsigned ? "%llu" : "%lld";
+ } else {
+ return is_unsigned ? "%u" : "%d";
+ }
+}
+
/* Forward declarations for internal functions */
static axis2_status_t create_output_directory(const axis2_char_t *path, const axutil_env_t *env);
static axis2_status_t generate_stub_header(wsdl2c_context_t *context, const axutil_env_t *env);
@@ -912,8 +1035,9 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
}
/* Map XSD types to C types */
else if (elem->type) {
- if (strstr(elem->type, "int") || strstr(elem->type, "Integer")) {
- c_type = "int";
+ /* AXIS2C-1492 FIX: Use helper function for proper integer type mapping */
+ if (is_integer_type(elem->type)) {
+ c_type = get_c_integer_type(elem->type);
} else if (strstr(elem->type, "boolean") || strstr(elem->type, "bool")) {
c_type = "axis2_bool_t";
} else if (strstr(elem->type, "double") || strstr(elem->type, "float")) {
@@ -1073,8 +1197,9 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
c_type = "axiom_node_t*";
}
else if (elem->type) {
- if (strstr(elem->type, "int") || strstr(elem->type, "Integer")) {
- c_type = "int";
+ /* AXIS2C-1492 FIX: Use helper function for proper integer type mapping */
+ if (is_integer_type(elem->type)) {
+ c_type = get_c_integer_type(elem->type);
} else if (strstr(elem->type, "boolean") || strstr(elem->type, "bool")) {
c_type = "axis2_bool_t";
} else if (strstr(elem->type, "double") || strstr(elem->type, "float")) {
@@ -1160,10 +1285,11 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
fprintf(source_file, " axutil_date_time_free(_this->%s, env);\n", elem_name);
fprintf(source_file, " }\n");
} else if (elem->type &&
- (strstr(elem->type, "int") || strstr(elem->type, "Integer") ||
+ (is_integer_type(elem->type) ||
strstr(elem->type, "boolean") || strstr(elem->type, "bool") ||
- strstr(elem->type, "double") || strstr(elem->type, "float"))) {
- /* Primitive types don't need freeing */
+ strstr(elem->type, "double") || strstr(elem->type, "float") ||
+ strstr(elem->type, "decimal"))) {
+ /* Primitive types don't need freeing - AXIS2C-1492 */
} else if (!elem->is_typeless && !elem->is_any_type) {
/* String types need AXIS2_FREE */
fprintf(source_file, " if (_this->%s) {\n", elem_name);
@@ -1199,8 +1325,9 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
default_val = "NULL";
}
else if (elem->type) {
- if (strstr(elem->type, "int") || strstr(elem->type, "Integer")) {
- c_type = "int";
+ /* AXIS2C-1492 FIX: Use helper function for proper integer type mapping */
+ if (is_integer_type(elem->type)) {
+ c_type = get_c_integer_type(elem->type);
default_val = "0";
} else if (strstr(elem->type, "boolean") || strstr(elem->type, "bool")) {
c_type = "axis2_bool_t";
@@ -1225,8 +1352,9 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
/* AXIS2C-1182: Generate array accessor functions */
/* Check if this is a primitive type that needs boxing */
+ /* AXIS2C-1492 FIX: Use helper function for integer type detection */
axis2_bool_t is_primitive = (elem->type &&
- (strstr(elem->type, "int") || strstr(elem->type, "Integer") ||
+ (is_integer_type(elem->type) ||
strstr(elem->type, "boolean") || strstr(elem->type, "bool") ||
strstr(elem->type, "double") || strstr(elem->type, "float")));
@@ -1369,8 +1497,9 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
if (is_array) {
/* AXIS2C-1182: Loop through array and serialize each item */
/* Check if this is a primitive type that needs unboxing */
+ /* AXIS2C-1492 FIX: Use helper function for integer type detection */
axis2_bool_t is_primitive = (elem->type &&
- (strstr(elem->type, "int") || strstr(elem->type, "Integer") ||
+ (is_integer_type(elem->type) ||
strstr(elem->type, "boolean") || strstr(elem->type, "bool") ||
strstr(elem->type, "double") || strstr(elem->type, "float")));
@@ -1380,13 +1509,16 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
if (is_primitive) {
/* Primitive types are boxed - need to unbox and convert to string */
- if (elem->type && (strstr(elem->type, "int") || strstr(elem->type, "Integer"))) {
- fprintf(source_file, " int *_arr_item = (int*)axutil_array_list_get(_this->%s, env, _ser_i);\n", elem_name);
+ /* AXIS2C-1492 FIX: Use proper integer type and format specifier */
+ if (elem->type && is_integer_type(elem->type)) {
+ const char *int_c_type = get_c_integer_type(elem->type);
+ const char *int_fmt = get_integer_format_specifier(elem->type);
+ fprintf(source_file, " %s *_arr_item = (%s*)axutil_array_list_get(_this->%s, env, _ser_i);\n", int_c_type, int_c_type, elem_name);
fprintf(source_file, " if (_arr_item) {\n");
fprintf(source_file, " ns = axiom_namespace_create(env, \"\", NULL);\n");
fprintf(source_file, " current_element = axiom_element_create(env, parent, \"%s\", ns, ¤t_node);\n", xml_name);
fprintf(source_file, " if (current_element) {\n");
- fprintf(source_file, " sprintf(tmp_buf, \"%%d\", *_arr_item);\n");
+ fprintf(source_file, " sprintf(tmp_buf, \"%s\", *_arr_item);\n", int_fmt);
fprintf(source_file, " axiom_element_set_text(current_element, env, tmp_buf, current_node);\n");
fprintf(source_file, " }\n");
fprintf(source_file, " }\n");
@@ -1448,8 +1580,10 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
fprintf(source_file, " AXIS2_FREE(env->allocator, text_value);\n");
fprintf(source_file, " text_value = NULL;\n");
fprintf(source_file, " }\n");
- } else if (elem->type && (strstr(elem->type, "int") || strstr(elem->type, "Integer"))) {
- fprintf(source_file, " sprintf(tmp_buf, \"%%d\", _this->%s);\n", elem_name);
+ /* AXIS2C-1492 FIX: Use proper format specifier for integer types */
+ } else if (elem->type && is_integer_type(elem->type)) {
+ const char *int_fmt = get_integer_format_specifier(elem->type);
+ fprintf(source_file, " sprintf(tmp_buf, \"%s\", _this->%s);\n", int_fmt, elem_name);
fprintf(source_file, " axiom_element_set_text(current_element, env, tmp_buf, current_node);\n");
} else if (elem->type && (strstr(elem->type, "boolean") || strstr(elem->type, "bool"))) {
fprintf(source_file, " axiom_element_set_text(current_element, env, _this->%s ? \"true\" : \"false\", current_node);\n", elem_name);
@@ -1518,8 +1652,9 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
if (is_array) {
/* AXIS2C-1182: Collect array elements into axutil_array_list_t */
/* Check if this is a primitive type that needs boxing */
+ /* AXIS2C-1492 FIX: Use helper function for integer type detection */
axis2_bool_t is_primitive = (elem->type &&
- (strstr(elem->type, "int") || strstr(elem->type, "Integer") ||
+ (is_integer_type(elem->type) ||
strstr(elem->type, "boolean") || strstr(elem->type, "bool") ||
strstr(elem->type, "double") || strstr(elem->type, "float")));
@@ -1531,10 +1666,13 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
if (is_primitive) {
/* Box primitive types when deserializing */
- if (elem->type && (strstr(elem->type, "int") || strstr(elem->type, "Integer"))) {
- fprintf(source_file, " int *_boxed = AXIS2_MALLOC(env->allocator, sizeof(int));\n");
+ /* AXIS2C-1492 FIX: Use proper integer type and conversion function */
+ if (elem->type && is_integer_type(elem->type)) {
+ const char *int_c_type = get_c_integer_type(elem->type);
+ const char *int_deser_func = get_integer_deserialize_func(elem->type);
+ fprintf(source_file, " %s *_boxed = AXIS2_MALLOC(env->allocator, sizeof(%s));\n", int_c_type, int_c_type);
fprintf(source_file, " if (_boxed) {\n");
- fprintf(source_file, " *_boxed = atoi(text_value);\n");
+ fprintf(source_file, " *_boxed = %s;\n", int_deser_func);
fprintf(source_file, " axutil_array_list_add(obj->%s, env, _boxed);\n", elem_name);
fprintf(source_file, " }\n");
} else if (elem->type && (strstr(elem->type, "boolean") || strstr(elem->type, "bool"))) {
@@ -1573,9 +1711,11 @@ generate_adb_complex_types(wsdl2c_context_t *context, const axutil_env_t *env)
fprintf(source_file, " axutil_date_time_deserialize_date_time(obj->%s, env, text_value);\n", elem_name);
fprintf(source_file, " }\n");
fprintf(source_file, " }\n");
- } else if (elem->type && (strstr(elem->type, "int") || strstr(elem->type, "Integer"))) {
+ /* AXIS2C-1492 FIX: Use proper integer conversion function */
+ } else if (elem->type && is_integer_type(elem->type)) {
+ const char *int_deser_func = get_integer_deserialize_func(elem->type);
fprintf(source_file, " if (text_value) {\n");
- fprintf(source_file, " obj->%s = atoi(text_value);\n", elem_name);
+ fprintf(source_file, " obj->%s = %s;\n", elem_name, int_deser_func);
fprintf(source_file, " }\n");
} else if (elem->type && (strstr(elem->type, "boolean") || strstr(elem->type, "bool"))) {
fprintf(source_file, " if (text_value) {\n");
diff --git a/tools/codegen/native/test/Makefile.am b/tools/codegen/native/test/Makefile.am
index 0ddc38902..96e96c54f 100644
--- a/tools/codegen/native/test/Makefile.am
+++ b/tools/codegen/native/test/Makefile.am
@@ -44,6 +44,7 @@ adb_test_runner_SOURCES = \
src/test_axis2c_1613_error_on_null.c \
src/test_axis2c_1182_array_add_function.c \
src/test_axis2c_1506_ehealth_schema.c \
+ src/test_axis2c_1492_unsigned_int.c \
src/axis2_stub_compat.c
# Include directories
diff --git a/tools/codegen/native/test/include/adb_test_framework.h b/tools/codegen/native/test/include/adb_test_framework.h
index 11f33c660..b3521333c 100644
--- a/tools/codegen/native/test/include/adb_test_framework.h
+++ b/tools/codegen/native/test/include/adb_test_framework.h
@@ -416,6 +416,17 @@ extern int axis2c_1182_test_count;
extern adb_test_case_t axis2c_1506_tests[];
extern int axis2c_1506_test_count;
+/* AXIS2C-1492: Unsigned integer type handling
+ *
+ * Issue: xsd:unsignedInt values above INT_MAX are truncated because
+ * the generated code uses atoi() which returns signed int.
+ *
+ * Fix: Uses proper type mapping (unsigned int, uint64_t) and
+ * conversion functions (strtoul, strtoull) for unsigned types.
+ */
+extern adb_test_case_t axis2c_1492_tests[];
+extern int axis2c_1492_test_count;
+
/* Global test statistics */
extern adb_test_stats_t g_test_stats;
diff --git a/tools/codegen/native/test/src/adb_test_framework.c b/tools/codegen/native/test/src/adb_test_framework.c
index 9953d4056..4616e50e0 100644
--- a/tools/codegen/native/test/src/adb_test_framework.c
+++ b/tools/codegen/native/test/src/adb_test_framework.c
@@ -472,6 +472,7 @@ int main(int argc, char *argv[]) {
adb_run_test_suite(axis2c_1613_tests, axis2c_1613_test_count);
adb_run_test_suite(axis2c_1182_tests, axis2c_1182_test_count);
adb_run_test_suite(axis2c_1506_tests, axis2c_1506_test_count);
+ adb_run_test_suite(axis2c_1492_tests, axis2c_1492_test_count);
adb_test_cleanup();
diff --git a/tools/codegen/native/test/src/test_axis2c_1492_unsigned_int.c b/tools/codegen/native/test/src/test_axis2c_1492_unsigned_int.c
new file mode 100644
index 000000000..dd92d899e
--- /dev/null
+++ b/tools/codegen/native/test/src/test_axis2c_1492_unsigned_int.c
@@ -0,0 +1,429 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * test_axis2c_1492_unsigned_int.c
+ *
+ * AXIS2C-1492 Tests for Unsigned Integer Type Handling
+ *
+ * Issue: xsd:unsignedInt values above 2147483647 are truncated because
+ * the generated code uses atoi() which returns signed int, causing
+ * values above INT_MAX to overflow to negative numbers.
+ *
+ * Fix: The native generator now uses proper type mapping and conversion:
+ * - xsd:unsignedInt -> unsigned int with strtoul()
+ * - xsd:unsignedLong -> uint64_t with strtoull()
+ * - xsd:unsignedShort -> unsigned int with strtoul()
+ * - xsd:unsignedByte -> unsigned int with strtoul()
+ *
+ * This ensures values like 4294967295 (max unsigned int) are handled
+ * correctly without overflow.
+ */
+
+#include "adb_test_framework.h"
+#include <stdint.h>
+#include <limits.h>
+
+/* Simulate the helper functions from stub_generator.c for testing
+ * These use the exact same logic as the actual implementation.
+ */
+
+/* Check if XSD type is an unsigned integer type */
+static int
+test_is_unsigned_integer_type(const char *xsd_type)
+{
+ if (!xsd_type) {
+ return 0;
+ }
+ if (strstr(xsd_type, "unsignedInt") ||
+ strstr(xsd_type, "unsignedLong") ||
+ strstr(xsd_type, "unsignedShort") ||
+ strstr(xsd_type, "unsignedByte") ||
+ strstr(xsd_type, "positiveInteger") ||
+ strstr(xsd_type, "nonNegativeInteger")) {
+ return 1;
+ }
+ return 0;
+}
+
+/* Check if XSD type is a 64-bit integer type (long) */
+static int
+test_is_64bit_integer_type(const char *xsd_type)
+{
+ if (!xsd_type) {
+ return 0;
+ }
+ if (strstr(xsd_type, "Long") || strstr(xsd_type, "long") ||
+ strstr(xsd_type, "integer") || strstr(xsd_type, "Integer")) {
+ /* "integer" in XSD is arbitrary precision, map to 64-bit */
+ /* But exclude unsignedInt which contains "int" */
+ if (strstr(xsd_type, "unsignedInt") && !strstr(xsd_type, "unsignedInteg")) {
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/* Check if XSD type is any integer type (signed or unsigned) */
+static int
+test_is_integer_type(const char *xsd_type)
+{
+ if (!xsd_type) {
+ return 0;
+ }
+ if (strstr(xsd_type, "int") || strstr(xsd_type, "Int") ||
+ strstr(xsd_type, "long") || strstr(xsd_type, "Long") ||
+ strstr(xsd_type, "short") || strstr(xsd_type, "Short") ||
+ strstr(xsd_type, "byte") || strstr(xsd_type, "Byte") ||
+ strstr(xsd_type, "integer") || strstr(xsd_type, "Integer")) {
+ return 1;
+ }
+ return 0;
+}
+
+/* Get the C type string for an XSD integer type */
+static const char*
+test_get_c_integer_type(const char *xsd_type)
+{
+ if (!xsd_type) {
+ return "int";
+ }
+
+ int is_unsigned = test_is_unsigned_integer_type(xsd_type);
+ int is_64bit = test_is_64bit_integer_type(xsd_type);
+
+ if (is_64bit) {
+ return is_unsigned ? "uint64_t" : "int64_t";
+ } else {
+ return is_unsigned ? "unsigned int" : "int";
+ }
+}
+
+/* Get the conversion function for deserializing an XSD integer type */
+static const char*
+test_get_deserialize_func(const char *xsd_type)
+{
+ if (!xsd_type) {
+ return "atoi";
+ }
+
+ int is_unsigned = test_is_unsigned_integer_type(xsd_type);
+ int is_64bit = test_is_64bit_integer_type(xsd_type);
+
+ if (is_64bit) {
+ return is_unsigned ? "strtoull" : "strtoll";
+ } else {
+ return is_unsigned ? "strtoul" : "atoi";
+ }
+}
+
+/* Get the printf format specifier for an XSD integer type */
+static const char*
+test_get_format_specifier(const char *xsd_type)
+{
+ if (!xsd_type) {
+ return "%d";
+ }
+
+ int is_unsigned = test_is_unsigned_integer_type(xsd_type);
+ int is_64bit = test_is_64bit_integer_type(xsd_type);
+
+ if (is_64bit) {
+ return is_unsigned ? "%llu" : "%lld";
+ } else {
+ return is_unsigned ? "%u" : "%d";
+ }
+}
+
+/* Test unsigned type detection */
+adb_test_result_t test_axis2c_1492_unsigned_type_detection(void) {
+ printf("Testing AXIS2C-1492: Unsigned type detection...\n");
+
+ struct {
+ const char *type;
+ int expected;
+ } tests[] = {
+ /* Unsigned types - should return true */
+ {"unsignedInt", 1},
+ {"xsd:unsignedInt", 1},
+ {"unsignedLong", 1},
+ {"unsignedShort", 1},
+ {"unsignedByte", 1},
+ {"positiveInteger", 1},
+ {"nonNegativeInteger", 1},
+ /* Signed types should return false */
+ {"int", 0},
+ {"xsd:int", 0},
+ {"long", 0},
+ {"short", 0},
+ {"byte", 0},
+ {"integer", 0},
+ {"negativeInteger", 0},
+ };
+
+ int count = sizeof(tests) / sizeof(tests[0]);
+ int i;
+ for (i = 0; i < count; i++) {
+ int result = test_is_unsigned_integer_type(tests[i].type);
+ printf(" is_unsigned_integer_type(\"%s\") = %s (expected %s)\n",
+ tests[i].type,
+ result ? "true" : "false",
+ tests[i].expected ? "true" : "false");
+ ADB_ASSERT_TRUE(result == tests[i].expected,
+ "Unsigned type detection should match expected");
+ }
+
+ printf(" Unsigned type detection: PASS\n");
+ return ADB_TEST_SUCCESS;
+}
+
+/* Test C type mapping */
+adb_test_result_t test_axis2c_1492_c_type_mapping(void) {
+ printf("Testing AXIS2C-1492: C type mapping...\n");
+
+ struct {
+ const char *xsd_type;
+ const char *expected_c_type;
+ } tests[] = {
+ /* Signed 32-bit */
+ {"int", "int"},
+ {"short", "int"},
+ {"byte", "int"},
+ /* Unsigned 32-bit - the AXIS2C-1492 fix */
+ {"unsignedInt", "unsigned int"},
+ {"unsignedShort", "unsigned int"},
+ {"unsignedByte", "unsigned int"},
+ /* Signed 64-bit */
+ {"long", "int64_t"},
+ {"integer", "int64_t"},
+ {"negativeInteger", "int64_t"},
+ /* Unsigned 64-bit */
+ {"unsignedLong", "uint64_t"},
+ {"positiveInteger", "uint64_t"},
+ {"nonNegativeInteger", "uint64_t"},
+ };
+
+ int count = sizeof(tests) / sizeof(tests[0]);
+ int i;
+ for (i = 0; i < count; i++) {
+ const char *result = test_get_c_integer_type(tests[i].xsd_type);
+ printf(" get_c_integer_type(\"%s\") = \"%s\" (expected \"%s\")\n",
+ tests[i].xsd_type, result, tests[i].expected_c_type);
+ ADB_ASSERT_TRUE(strcmp(result, tests[i].expected_c_type) == 0,
+ "C type mapping should match expected");
+ }
+
+ printf(" C type mapping: PASS\n");
+ return ADB_TEST_SUCCESS;
+}
+
+/* Test conversion function selection */
+adb_test_result_t test_axis2c_1492_conversion_functions(void) {
+ printf("Testing AXIS2C-1492: Conversion function selection...\n");
+
+ struct {
+ const char *xsd_type;
+ const char *expected_func;
+ } tests[] = {
+ /* Signed 32-bit uses atoi */
+ {"int", "atoi"},
+ {"short", "atoi"},
+ {"byte", "atoi"},
+ /* Unsigned 32-bit uses strtoul - the AXIS2C-1492 fix */
+ {"unsignedInt", "strtoul"},
+ {"unsignedShort", "strtoul"},
+ {"unsignedByte", "strtoul"},
+ /* Signed 64-bit uses strtoll */
+ {"long", "strtoll"},
+ {"integer", "strtoll"},
+ /* Unsigned 64-bit uses strtoull */
+ {"unsignedLong", "strtoull"},
+ {"positiveInteger", "strtoull"},
+ };
+
+ int count = sizeof(tests) / sizeof(tests[0]);
+ int i;
+ for (i = 0; i < count; i++) {
+ const char *result = test_get_deserialize_func(tests[i].xsd_type);
+ printf(" get_deserialize_func(\"%s\") = \"%s\" (expected \"%s\")\n",
+ tests[i].xsd_type, result, tests[i].expected_func);
+ ADB_ASSERT_TRUE(strcmp(result, tests[i].expected_func) == 0,
+ "Conversion function should match expected");
+ }
+
+ printf(" Conversion function selection: PASS\n");
+ return ADB_TEST_SUCCESS;
+}
+
+/* Test format specifier selection */
+adb_test_result_t test_axis2c_1492_format_specifiers(void) {
+ printf("Testing AXIS2C-1492: Format specifier selection...\n");
+
+ struct {
+ const char *xsd_type;
+ const char *expected_format;
+ } tests[] = {
+ /* Signed 32-bit uses %d */
+ {"int", "%d"},
+ {"short", "%d"},
+ {"byte", "%d"},
+ /* Unsigned 32-bit uses %u - the AXIS2C-1492 fix */
+ {"unsignedInt", "%u"},
+ {"unsignedShort", "%u"},
+ {"unsignedByte", "%u"},
+ /* Signed 64-bit uses %lld */
+ {"long", "%lld"},
+ {"integer", "%lld"},
+ /* Unsigned 64-bit uses %llu */
+ {"unsignedLong", "%llu"},
+ {"positiveInteger", "%llu"},
+ };
+
+ int count = sizeof(tests) / sizeof(tests[0]);
+ int i;
+ for (i = 0; i < count; i++) {
+ const char *result = test_get_format_specifier(tests[i].xsd_type);
+ printf(" get_format_specifier(\"%s\") = \"%s\" (expected \"%s\")\n",
+ tests[i].xsd_type, result, tests[i].expected_format);
+ ADB_ASSERT_TRUE(strcmp(result, tests[i].expected_format) == 0,
+ "Format specifier should match expected");
+ }
+
+ printf(" Format specifier selection: PASS\n");
+ return ADB_TEST_SUCCESS;
+}
+
+/* Test the actual bug: large unsigned values */
+adb_test_result_t test_axis2c_1492_large_unsigned_values(void) {
+ printf("Testing AXIS2C-1492: Large unsigned value handling...\n");
+
+ /* Test value that would overflow if using atoi */
+ const char *text_value = "3000000000"; /* Greater than INT_MAX (2147483647) */
+
+ /* Old buggy approach: atoi() returns signed int, causes overflow */
+ int buggy_result = atoi(text_value);
+ printf(" Old buggy atoi(\"%s\") = %d (WRONG - overflow to negative)\n",
+ text_value, buggy_result);
+ ADB_ASSERT_TRUE(buggy_result < 0, "atoi should overflow to negative for large values");
+
+ /* New fixed approach: strtoul() returns unsigned, no overflow */
+ unsigned int fixed_result = strtoul(text_value, NULL, 10);
+ printf(" New fixed strtoul(\"%s\") = %u (CORRECT)\n",
+ text_value, fixed_result);
+ ADB_ASSERT_TRUE(fixed_result == 3000000000U, "strtoul should handle large unsigned values");
+
+ /* Test maximum unsigned int value */
+ const char *max_uint = "4294967295";
+ unsigned int max_result = strtoul(max_uint, NULL, 10);
+ printf(" strtoul(\"%s\") = %u (max unsigned int)\n", max_uint, max_result);
+ ADB_ASSERT_TRUE(max_result == UINT_MAX, "strtoul should handle max unsigned int");
+
+ /* Test maximum uint64_t value */
+ const char *max_uint64 = "18446744073709551615";
+ uint64_t max64_result = strtoull(max_uint64, NULL, 10);
+ printf(" strtoull(\"%s\") = %llu (max uint64_t)\n",
+ max_uint64, (unsigned long long)max64_result);
+ ADB_ASSERT_TRUE(max64_result == UINT64_MAX, "strtoull should handle max uint64_t");
+
+ printf(" Large unsigned value handling: PASS\n");
+ return ADB_TEST_SUCCESS;
+}
+
+/* Test integer type detection (for free function primitive check) */
+adb_test_result_t test_axis2c_1492_integer_type_detection(void) {
+ printf("Testing AXIS2C-1492: Integer type detection (for free function)...\n");
+
+ struct {
+ const char *type;
+ int expected;
+ } tests[] = {
+ /* All integer types should be detected */
+ {"int", 1},
+ {"xsd:int", 1},
+ {"unsignedInt", 1},
+ {"long", 1},
+ {"unsignedLong", 1},
+ {"short", 1},
+ {"unsignedShort", 1},
+ {"byte", 1},
+ {"unsignedByte", 1},
+ {"integer", 1},
+ {"positiveInteger", 1},
+ {"negativeInteger", 1},
+ {"nonNegativeInteger", 1},
+ {"nonPositiveInteger", 1},
+ /* Non-integer types should NOT be detected */
+ {"string", 0},
+ {"dateTime", 0},
+ {"base64Binary", 0},
+ {"boolean", 0},
+ {"double", 0},
+ {"float", 0},
+ };
+
+ int count = sizeof(tests) / sizeof(tests[0]);
+ int i;
+ for (i = 0; i < count; i++) {
+ int result = test_is_integer_type(tests[i].type);
+ printf(" is_integer_type(\"%s\") = %s (expected %s)\n",
+ tests[i].type,
+ result ? "true" : "false",
+ tests[i].expected ? "true" : "false");
+ ADB_ASSERT_TRUE(result == tests[i].expected,
+ "Integer type detection should match expected");
+ }
+
+ printf(" Integer type detection: PASS\n");
+ return ADB_TEST_SUCCESS;
+}
+
+/* Test case array for AXIS2C-1492 tests */
+adb_test_case_t axis2c_1492_tests[] = {
+ {
+ "test_axis2c_1492_unsigned_type_detection",
+ "Test XSD unsigned type detection",
+ test_axis2c_1492_unsigned_type_detection
+ },
+ {
+ "test_axis2c_1492_c_type_mapping",
+ "Test XSD to C type mapping",
+ test_axis2c_1492_c_type_mapping
+ },
+ {
+ "test_axis2c_1492_conversion_functions",
+ "Test string-to-integer conversion function selection",
+ test_axis2c_1492_conversion_functions
+ },
+ {
+ "test_axis2c_1492_format_specifiers",
+ "Test printf format specifier selection",
+ test_axis2c_1492_format_specifiers
+ },
+ {
+ "test_axis2c_1492_large_unsigned_values",
+ "Test large unsigned value handling (the actual bug)",
+ test_axis2c_1492_large_unsigned_values
+ },
+ {
+ "test_axis2c_1492_integer_type_detection",
+ "Test integer type detection (for free function primitive check)",
+ test_axis2c_1492_integer_type_detection
+ }
+};
+
+int axis2c_1492_test_count = sizeof(axis2c_1492_tests) / sizeof(axis2c_1492_tests[0]);