From e0f2a5b46bc026efa6737fa9e69f2b526fb8b39e Mon Sep 17 00:00:00 2001
From: Lev Walkin <vlm@lionet.info>
Date: Wed, 30 Aug 2017 20:02:29 -0700
Subject: [PATCH] 0..MAX is unsigned in constraints

---
 libasn1compiler/asn1c_constraint.c            | 19 ++++++++++++-------
 libasn1compiler/asn1c_misc.c                  |  3 +++
 .../50-constraint-OK.asn1.-Pgen-PER           |  2 +-
 .../90-cond-int-type-OK.asn1.-P               | 13 +++++++++----
 .../90-cond-int-type-OK.asn1.-Pgen-PER        | 13 +++++++++----
 5 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/libasn1compiler/asn1c_constraint.c b/libasn1compiler/asn1c_constraint.c
index 24023f09..bd6087e0 100644
--- a/libasn1compiler/asn1c_constraint.c
+++ b/libasn1compiler/asn1c_constraint.c
@@ -12,16 +12,16 @@ static int emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, as
 static int emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype);
 static asn1p_expr_type_e _find_terminal_type(arg_t *arg);
 static int emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1c_integer_t natural_start, asn1c_integer_t natural_stop);
-static int native_long_sign(asn1cnst_range_t *r);	/* -1, 0, 1 */
+static int native_long_sign(arg_t *arg, asn1cnst_range_t *r);	/* -1, 0, 1 */
 
 static int
-ulong_optimization(asn1p_expr_type_e etype, asn1cnst_range_t *r_size,
+ulong_optimization(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_range_t *r_size,
 						asn1cnst_range_t *r_value)
 {
 	return (!r_size && r_value
 		&& (etype == ASN_BASIC_INTEGER
 		|| etype == ASN_BASIC_ENUMERATED)
-		&& native_long_sign(r_value) == 0);
+		&& native_long_sign(arg, r_value) == 0);
 }
 
 int
@@ -104,8 +104,8 @@ asn1c_emit_constraint_checking_code(arg_t *arg) {
 			switch(etype) {
 			case ASN_BASIC_INTEGER:
 			case ASN_BASIC_ENUMERATED:
-				if(native_long_sign(r_value) >= 0) {
-					ulong_optimize = ulong_optimization(etype, r_size, r_value);
+				if(native_long_sign(arg, r_value) >= 0) {
+					ulong_optimize = ulong_optimization(arg, etype, r_size, r_value);
 					if(!ulong_optimize) {
 						OUT("unsigned long value;\n");
 					}
@@ -643,7 +643,7 @@ emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_rang
 				break;
 			}
 
-			if(native_long_sign(r_value) >= 0) {
+			if(native_long_sign(arg, r_value) >= 0) {
 				/* Special case for treating unsigned longs */
 				OUT("if(asn_INTEGER2ulong(st, &value)) {\n");
 				INDENT(+1);
@@ -710,7 +710,12 @@ _find_terminal_type(arg_t *arg) {
 }
 
 static int
-native_long_sign(asn1cnst_range_t *r) {
+native_long_sign(arg_t *arg, asn1cnst_range_t *r) {
+    if(!(arg->flags & A1C_USE_WIDE_TYPES) && r->left.type == ARE_VALUE
+       && r->left.value >= 0 && r->left.value <= 2147483647
+        && r->right.type == ARE_MAX) {
+        return 1;
+    }
 	if(r->left.type == ARE_VALUE
 	&& r->left.value >= 0
 	&& r->right.type == ARE_VALUE
diff --git a/libasn1compiler/asn1c_misc.c b/libasn1compiler/asn1c_misc.c
index 665b748e..99c275b2 100644
--- a/libasn1compiler/asn1c_misc.c
+++ b/libasn1compiler/asn1c_misc.c
@@ -406,6 +406,9 @@ asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr) {
 	asn1constraint_range_free(range);
 
 	/* Special case for unsigned */
+    if(!(arg->flags & A1C_USE_WIDE_TYPES) && left.type == ARE_VALUE
+       && left.value >= 0 && left.value <= 2147483647 && right.type == ARE_MAX)
+        return FL_FITS_UNSIGN;
 	if(left.type == ARE_VALUE
 		&& left.value >= 0
 	&& right.type == ARE_VALUE
diff --git a/tests/tests-asn1c-compiler/50-constraint-OK.asn1.-Pgen-PER b/tests/tests-asn1c-compiler/50-constraint-OK.asn1.-Pgen-PER
index 7020fd2c..6499e919 100644
--- a/tests/tests-asn1c-compiler/50-constraint-OK.asn1.-Pgen-PER
+++ b/tests/tests-asn1c-compiler/50-constraint-OK.asn1.-Pgen-PER
@@ -77,7 +77,7 @@ per_type_encoder_f Int2_encode_uper;
 int
 Int2_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
-	long value;
+	unsigned long value;
 	
 	if(!sptr) {
 		ASN__CTFAIL(app_key, td, sptr,
diff --git a/tests/tests-asn1c-compiler/90-cond-int-type-OK.asn1.-P b/tests/tests-asn1c-compiler/90-cond-int-type-OK.asn1.-P
index 7b280523..2767118c 100644
--- a/tests/tests-asn1c-compiler/90-cond-int-type-OK.asn1.-P
+++ b/tests/tests-asn1c-compiler/90-cond-int-type-OK.asn1.-P
@@ -356,7 +356,7 @@ asn_TYPE_descriptor_t asn_DEF_NO_IntegerLowHigh = {
 
 /*** <<< TYPE-DECLS [CN-IntegerLowMax] >>> ***/
 
-typedef long	 CN_IntegerLowMax_t;
+typedef unsigned long	 CN_IntegerLowMax_t;
 
 /*** <<< FUNC-DECLS [CN-IntegerLowMax] >>> ***/
 
@@ -374,7 +374,7 @@ xer_type_encoder_f CN_IntegerLowMax_encode_xer;
 int
 CN_IntegerLowMax_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
-	long value;
+	unsigned long value;
 	
 	if(!sptr) {
 		ASN__CTFAIL(app_key, td, sptr,
@@ -383,7 +383,7 @@ CN_IntegerLowMax_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 		return -1;
 	}
 	
-	value = *(const long *)sptr;
+	value = *(const unsigned long *)sptr;
 	
 	if((value >= 1)) {
 		/* Constraint check succeeded */
@@ -403,6 +403,11 @@ CN_IntegerLowMax_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 
 /*** <<< STAT-DEFS [CN-IntegerLowMax] >>> ***/
 
+static const asn_INTEGER_specifics_t asn_SPC_CN_IntegerLowMax_specs_1 = {
+	0,	0,	0,	0,	0,
+	0,	/* Native long size */
+	1	/* Unsigned representation */
+};
 static const ber_tlv_tag_t asn_DEF_CN_IntegerLowMax_tags_1[] = {
 	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
 };
@@ -420,7 +425,7 @@ asn_TYPE_descriptor_t asn_DEF_CN_IntegerLowMax = {
 	0,	/* No OER visible constraints */
 	0,	/* No PER visible constraints */
 	0, 0,	/* No members */
-	0	/* No specifics */
+	&asn_SPC_CN_IntegerLowMax_specs_1	/* Additional specs */
 };
 
 
diff --git a/tests/tests-asn1c-compiler/90-cond-int-type-OK.asn1.-Pgen-PER b/tests/tests-asn1c-compiler/90-cond-int-type-OK.asn1.-Pgen-PER
index 68101885..c6bdd60d 100644
--- a/tests/tests-asn1c-compiler/90-cond-int-type-OK.asn1.-Pgen-PER
+++ b/tests/tests-asn1c-compiler/90-cond-int-type-OK.asn1.-Pgen-PER
@@ -398,7 +398,7 @@ asn_TYPE_descriptor_t asn_DEF_NO_IntegerLowHigh = {
 
 /*** <<< TYPE-DECLS [CN-IntegerLowMax] >>> ***/
 
-typedef long	 CN_IntegerLowMax_t;
+typedef unsigned long	 CN_IntegerLowMax_t;
 
 /*** <<< FUNC-DECLS [CN-IntegerLowMax] >>> ***/
 
@@ -418,7 +418,7 @@ per_type_encoder_f CN_IntegerLowMax_encode_uper;
 int
 CN_IntegerLowMax_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
-	long value;
+	unsigned long value;
 	
 	if(!sptr) {
 		ASN__CTFAIL(app_key, td, sptr,
@@ -427,7 +427,7 @@ CN_IntegerLowMax_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 		return -1;
 	}
 	
-	value = *(const long *)sptr;
+	value = *(const unsigned long *)sptr;
 	
 	if((value >= 1)) {
 		/* Constraint check succeeded */
@@ -455,6 +455,11 @@ static asn_per_constraints_t asn_PER_type_CN_IntegerLowMax_constr_1 GCC_NOTUSED
 
 /*** <<< STAT-DEFS [CN-IntegerLowMax] >>> ***/
 
+static const asn_INTEGER_specifics_t asn_SPC_CN_IntegerLowMax_specs_1 = {
+	0,	0,	0,	0,	0,
+	0,	/* Native long size */
+	1	/* Unsigned representation */
+};
 static const ber_tlv_tag_t asn_DEF_CN_IntegerLowMax_tags_1[] = {
 	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
 };
@@ -472,7 +477,7 @@ asn_TYPE_descriptor_t asn_DEF_CN_IntegerLowMax = {
 	0,	/* No OER visible constraints */
 	&asn_PER_type_CN_IntegerLowMax_constr_1,
 	0, 0,	/* No members */
-	0	/* No specifics */
+	&asn_SPC_CN_IntegerLowMax_specs_1	/* Additional specs */
 };
 
 
-- 
2.26.2