get rid of undefined behavior and narrow supported entity reference range
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index 844c6f2..d101593 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -936,16 +936,13 @@
  */
 static int
 OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) {
+	const int32_t last_unicode_codepoint = 0x10ffff;
 	int32_t val = 0;
 	const char *p;
 
 	for(p = buf; p < end; p++) {
 		int ch = *p;
 
-		/* Strange huge value */
-		if((val * base + base) < 0)
-			return -1;
-
 		switch(ch) {
 		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
 		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
@@ -965,6 +962,11 @@
 		default:
 			return -1;	/* Character set error */
 		}
+
+		/* Value exceeds the Unicode range. */
+		if(val > last_unicode_codepoint) {
+			return -1;
+		}
 	}
 
 	*ret_value = -1;
diff --git a/tests/tests-skeletons/check-OCTET_STRING.c b/tests/tests-skeletons/check-OCTET_STRING.c
index 30564c1..bfbfc8f 100644
--- a/tests/tests-skeletons/check-OCTET_STRING.c
+++ b/tests/tests-skeletons/check-OCTET_STRING.c
@@ -8,8 +8,10 @@
 
 enum encoding_type { HEX, BINARY, UTF8 };
 
+#define check(t, tag, buf, verify)  check_impl(__LINE__, t, tag, buf, verify)
+
 static void
-check(enum encoding_type type, char *tagname, char *xmlbuf, char *verify) {
+check_impl(int lineno, enum encoding_type type, char *tagname, char *xmlbuf, char *verify) {
 	size_t xmllen = strlen(xmlbuf);
 	size_t verlen = verify ? strlen(verify) : 0;
 	asn_TYPE_descriptor_t *td = &asn_DEF_OCTET_STRING;
@@ -32,8 +34,8 @@
 	}
 
 	rc = decoder(0, td, (void **)stp, tagname, xmlbuf, xmllen);
-	printf("[%s] => [%s]:%zu vs [%s]:%zu, code %d\n",
-		xmlbuf,
+	printf("%03d: [%s] => [%s]:%zu vs [%s]:%zu, code %d\n",
+		lineno, xmlbuf,
 		st ? (const char *)st->buf : "", st ? st->size : 0,
 		verify ? verify : "", verlen, rc.code);
 
@@ -123,6 +125,13 @@
 	check(UTF8, "z", "<z z z>a&#x20;b</z z z>", "a b");
 	check(UTF8, "z", "<z z z>a&#32;b</z z z>", "a b");
 	check(UTF8, "z", "<z>a&#32323;b</z>", "a\347\271\203b");
+	check(UTF8, "z", "<z>a&#x4fc4;|</z>", "a\xe4\xbf\x84|");
+    /* Last unicode point */
+	check(UTF8, "z", "<z>a&#x10ffff;|</z>", "a\xf4\x8f\xbf\xbf|");
+	check(UTF8, "z", "<z>a&#1114111;|</z>", "a\xf4\x8f\xbf\xbf|");
+    /* One past the last unicode point */
+	check(UTF8, "z", "<z>a&#x110000;|</z>", "a&#x110000;|");
+	check(UTF8, "z", "<z>a&#1114112;|</z>", "a&#1114112;|");
 	check(UTF8, "z", "<z>a&#3000000000;b</z>", "a&#3000000000;b");
 	check(UTF8, "z", "<z>a&#5000000000;b</z>", "a&#5000000000;b");
 	check(UTF8, "z", "<z>a&#300</z>", "a&#300");