static int traverse_string(const unsigned char *p, int len, int inform, int (*rfunc)(unsigned long value, void *in), void *arg) { unsigned long value; int ret; while (len) { switch (inform) { case MBSTRING_ASC: value = *p++; len--; break; case MBSTRING_BMP: value = *p++ << 8; value |= *p++; /* BMP is explictly defined to not support surrogates */ if (UNICODE_IS_SURROGATE(value)) return -1; len -= 2; break; case MBSTRING_UNIV: value = (unsigned long)*p++ << 24; value |= *p++ << 16; value |= *p++ << 8; value |= *p++; if (value > UNICODE_MAX || UNICODE_IS_SURROGATE(value)) return -1; len -= 4; break; default: ret = UTF8_getc(p, len, &value); if (ret < 0) return -1; len -= ret; p += ret; break; } if (rfunc) { ret = rfunc(value, arg); if (ret <= 0) return ret; } } return 1; }
static int do_buf(unsigned char *buf, int buflen, int type, unsigned char flags, char *quotes, char_io *io_ch, void *arg) { int i, outlen, len; unsigned char orflags, *p, *q; unsigned long c; p = buf; q = buf + buflen; outlen = 0; while (p != q) { if (p == buf && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_FIRST_ESC_2253; else orflags = 0; switch (type & BUF_TYPE_WIDTH_MASK) { case 4: c = ((unsigned long)*p++) << 24; c |= ((unsigned long)*p++) << 16; c |= ((unsigned long)*p++) << 8; c |= *p++; if (c > UNICODE_MAX || UNICODE_IS_SURROGATE(c)) return -1; break; case 2: c = ((unsigned long)*p++) << 8; c |= *p++; if (UNICODE_IS_SURROGATE(c)) return -1; break; case 1: c = *p++; break; case 0: i = UTF8_getc(p, q - p, &c); if (i < 0) return -1; /* Invalid UTF8String */ p += i; break; default: return -1; /* invalid width */ } if (p == q && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_LAST_ESC_2253; if (type & BUF_TYPE_CONVUTF8) { unsigned char utfbuf[6]; int utflen; utflen = UTF8_putc(utfbuf, sizeof utfbuf, c); if (utflen < 0) return -1; for (i = 0; i < utflen; i++) { /* We don't need to worry about setting orflags correctly * because if utflen==1 its value will be correct anyway * otherwise each character will be > 0x7f and so the * character will never be escaped on first and last. */ len = do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), quotes, io_ch, arg); if (len < 0) return -1; outlen += len; } } else { len = do_esc_char(c, (unsigned char)(flags | orflags), quotes, io_ch, arg); if (len < 0) return -1; outlen += len; } } return outlen; }