+static
+int str_check(size_t str_len, size_t offset, size_t len)
+{
+ /* check overflow */
+ if (offset + len < offset)
+ return -1;
+ if (offset + len > str_len)
+ return -1;
+ return 0;
+}
+
+static
+int import_basic_string(struct ctf_scanner *scanner, YYSTYPE *lvalp,
+ size_t len, const char *src, char delim)
+{
+ size_t pos = 0, dpos = 0;
+
+ if (str_check(len, pos, 1))
+ return -1;
+ if (src[pos++] != delim)
+ return -1;
+
+ while (src[pos] != delim) {
+ char c;
+
+ if (str_check(len, pos, 1))
+ return -1;
+ c = src[pos++];
+ if (c == '\\') {
+ if (str_check(len, pos, 1))
+ return -1;
+ c = src[pos++];
+
+ switch (c) {
+ case '0':
+ c = '\0';
+ break;
+ case 'a':
+ c = '\a';
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ case '\\':
+ c = '\\';
+ break;
+ case '\'':
+ c = '\'';
+ break;
+ case '\"':
+ c = '\"';
+ break;
+ case '?':
+ c = '?';
+ break;
+ case 'o':
+ {
+ size_t oct_len = 3;
+
+ if (str_check(len, pos, oct_len))
+ return -1;
+ if (!isdigit((int) src[pos]) || !isdigit((int) src[pos+1]) || !isdigit((int) src[pos+2]))
+ return -1;
+ char oct_buffer[4] = { src[pos], src[pos+1], src[pos+2], '\0' };
+ c = strtoul(&oct_buffer[0], NULL, 8);
+ pos += oct_len;
+ break;
+ }
+ case 'x':
+ {
+ size_t hex_len = 2;
+
+ if (str_check(len, pos, hex_len))
+ return -1;
+ if (!isxdigit((int) src[pos]) || !isxdigit((int) src[pos+1]))
+ return -1;
+ char hex_buffer[3] = { src[pos], src[pos+1], '\0' };
+ c = strtoul(&hex_buffer[0], NULL, 16);
+ pos += hex_len;
+ break;
+ }
+ default:
+ return -1;
+ }
+ }
+ if (str_check(len, dpos, 1))
+ return -1;
+ lvalp->gs->s[dpos++] = c;
+ }
+
+ if (str_check(len, dpos, 1))
+ return -1;
+ lvalp->gs->s[dpos++] = '\0';
+
+ if (str_check(len, pos, 1))
+ return -1;
+ if (src[pos++] != delim)
+ return -1;
+
+ if (str_check(len, pos, 1))
+ return -1;
+ if (src[pos] != '\0')
+ return -1;
+ return 0;
+}
+
+int import_string(struct ctf_scanner *scanner, YYSTYPE *lvalp,
+ const char *src, char delim)
+{
+ size_t len;
+
+ len = strlen(src) + 1;
+ lvalp->gs = gc_string_alloc(scanner, len);
+ if (src[0] == 'L') {
+ // TODO: import wide string
+ printfl_error(yyget_lineno(scanner),
+ "Wide string not supported yet.");
+ return -1;
+ } else {
+ return import_basic_string(scanner, lvalp, len, src, delim);
+ }
+}
+