* Parse a string. * * Three arguments (ctx->args) are retrieved from the stack to store data, * its actual length and address (in that order). */
| 10850 | * its actual length and address (in that order). |
| 10851 | */ |
| 10852 | static int |
| 10853 | parse_string(struct context *ctx, const struct token *token, |
| 10854 | const char *str, unsigned int len, |
| 10855 | void *buf, unsigned int size) |
| 10856 | { |
| 10857 | const struct arg *arg_data = pop_args(ctx); |
| 10858 | const struct arg *arg_len = pop_args(ctx); |
| 10859 | const struct arg *arg_addr = pop_args(ctx); |
| 10860 | char tmp[16]; /* Ought to be enough. */ |
| 10861 | int ret; |
| 10862 | |
| 10863 | /* Arguments are expected. */ |
| 10864 | if (!arg_data) |
| 10865 | return -1; |
| 10866 | if (!arg_len) { |
| 10867 | push_args(ctx, arg_data); |
| 10868 | return -1; |
| 10869 | } |
| 10870 | if (!arg_addr) { |
| 10871 | push_args(ctx, arg_len); |
| 10872 | push_args(ctx, arg_data); |
| 10873 | return -1; |
| 10874 | } |
| 10875 | size = arg_data->size; |
| 10876 | /* Bit-mask fill is not supported. */ |
| 10877 | if (arg_data->mask || size < len) |
| 10878 | goto error; |
| 10879 | if (!ctx->object) |
| 10880 | return len; |
| 10881 | /* Let parse_int() fill length information first. */ |
| 10882 | ret = snprintf(tmp, sizeof(tmp), "%u", len); |
| 10883 | if (ret < 0) |
| 10884 | goto error; |
| 10885 | push_args(ctx, arg_len); |
| 10886 | ret = parse_int(ctx, token, tmp, ret, NULL, 0); |
| 10887 | if (ret < 0) { |
| 10888 | pop_args(ctx); |
| 10889 | goto error; |
| 10890 | } |
| 10891 | buf = (uint8_t *)ctx->object + arg_data->offset; |
| 10892 | /* Output buffer is not necessarily NUL-terminated. */ |
| 10893 | memcpy(buf, str, len); |
| 10894 | memset((uint8_t *)buf + len, 0x00, size - len); |
| 10895 | if (ctx->objmask) |
| 10896 | memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); |
| 10897 | /* Save address if requested. */ |
| 10898 | if (arg_addr->size) { |
| 10899 | memcpy((uint8_t *)ctx->object + arg_addr->offset, |
| 10900 | (void *[]){ |
| 10901 | (uint8_t *)ctx->object + arg_data->offset |
| 10902 | }, |
| 10903 | arg_addr->size); |
| 10904 | if (ctx->objmask) |
| 10905 | memcpy((uint8_t *)ctx->objmask + arg_addr->offset, |
| 10906 | (void *[]){ |
| 10907 | (uint8_t *)ctx->objmask + arg_data->offset |
| 10908 | }, |
| 10909 | arg_addr->size); |