commit f69017607010372aaecdf65e4aca6ed5b25bf846
parent 9005e5c975d57701622880ac9ff93fecf92f2e6b
Author: William Casarin <jb55@jb55.com>
Date: Wed, 19 Jun 2019 00:36:33 -0700
decode: parse more bad inputs
it will try to parse until it can't any longer, and then it
will continue to print the remaining line.
This is useful for things like:
bitcoin-iterate -q --cache=cache --output=$'%os,%th' \
--start 500000 --blockdir=/zbig/bitcoin2/blocks \
| btcs -a -d \
| awk -F, '!x[$1]++'
HASH160 data(20) EQUAL,2157b554dcfda405233906e461ee593875ae4b1b97615872db6a25130ecc1dd6
RETURN data(36),2157b554dcfda405233906e461ee593875ae4b1b97615872db6a25130ecc1dd6
DUP HASH160 data(20) EQUALVERIFY CHECKSIG,1024cb12a576b69defa67dbc2f1899700ab58e5ad3d5e058edefb907f59865bc
RETURN data(20),8662e51ae3e9a8a050dc958a95ea27015107388ba212e483755121427e7ba2b7
0 data(20),761619410d9f2a7fa69336583a0351dd86caf9ed2cee8765132a93caa44f77de
0 data(32),577819ae38ccd0d2b931aeec4f83801ad3c42b3158d4ceb4874f2ef482f1d805
RETURN data(17),af41a3eb6505c08003195be6affd3961e45278b45d58d0a427532eeb67501353
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
4 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/main.c b/main.c
@@ -125,15 +125,16 @@ static void fail(int err, const char *msg)
}
-static int decompile(const char *str, int strlen, bool abbrev_data)
+static int decompile(const char *str, size_t *strlen, bool abbrev_data)
{
static u8 buf[10000];
- if (strlen % 2 != 0)
+ hex_decode(str, strlen, buf, sizeof(buf));
+
+ if (*strlen % 2 != 0)
return 0;
- hex_decode(str, strlen, buf, sizeof(buf));
- size_t nbytes = strlen / 2;
+ size_t nbytes = *strlen / 2;
script_print(buf, nbytes, abbrev_data);
@@ -203,14 +204,18 @@ int main(int argc, const char *argv[])
if (is_decompile) {
// we have stdin
char *line = NULL;
- ssize_t len = 0;
+ ssize_t len = 0, prevlen;
size_t n;
int ok;
bool failed = false;
if (input == NULL) {
while ((len = getline(&line, &n, stdin)) != -1) {
- ok = decompile(line, len-1, abbrev_data);
+ len--;
+ prevlen = len;
+ ok = decompile(line, (size_t*)&len, abbrev_data);
+
+ printf("%.*s\n", (int)(prevlen - len), line+len);
if (!ok) {
failed = true;
@@ -224,7 +229,8 @@ int main(int argc, const char *argv[])
if (!ok)
fail(4, "failed to read input arg (too big?)");
- ok = decompile((const char *)buf, written, abbrev_data);
+ ok = decompile((const char *)buf, &written, abbrev_data);
+ printf("\n");
if (!ok) {
fprintf(stderr, "failed to decompile\n");
diff --git a/script.c b/script.c
@@ -755,24 +755,27 @@ void script_print(const u8 *script, size_t script_size, int abbrev_data) {
static u8 tmpbuf[4096];
const u8 *p = script;
const u8 *top = script + script_size;
+ bool first = true;
while (p < top) {
enum opcode opcode;
script_getop(&p, top, &opcode, tmpbuf, sizeof(tmpbuf), &len);
+ if (!first)
+ putchar(' ');
+ first = false;
+
if (is_push_data(opcode)) {
if (abbrev_data)
printf("data(%d)", len);
else
hex_print(tmpbuf, len);
- printf(" ");
}
else
- printf("%s ", op_name(opcode));
+ printf("%s", op_name(opcode));
len = 0;
}
- printf("\n");
}
void script_print_vals(struct stack *stack) {
diff --git a/util.c b/util.c
@@ -1,6 +1,7 @@
#include "util.h"
#include <errno.h>
+#include <assert.h>
static bool char_to_hex(unsigned char *val, char c)
{
@@ -19,22 +20,25 @@ static bool char_to_hex(unsigned char *val, char c)
return false;
}
-bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize)
+bool hex_decode(const char *str, size_t *slen, void *buf, size_t bufsize)
{
unsigned char v1, v2;
unsigned char *p = buf;
+ int len = 0;
- while (slen > 1) {
- if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1]))
- return false;
- if (!bufsize)
+ while (*slen > 1) {
+ if (!bufsize || !char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1])) {
+ *slen = len;
return false;
+ }
*(p++) = (v1 << 4) | v2;
str += 2;
- slen -= 2;
+ *slen -= 2;
bufsize--;
+ len += 2;
}
- return slen == 0 && bufsize == 0;
+ *slen = len;
+ return *slen == 0 && bufsize == 0;
}
@@ -109,13 +113,12 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
int read_arg_or_stdin(const char *arg, unsigned char *buf, size_t buflen,
size_t *written)
{
- unsigned char dummy;
if (arg != NULL) {
unsigned char *p = buf;
bool done = false;
for (size_t i = 0; i < buflen; i++) {
*p = arg[i];
- if (*p == 0 || !char_to_hex(&dummy, *p)) {
+ if (*p == 0 ) {
done = true;
break;
}
diff --git a/util.h b/util.h
@@ -11,7 +11,7 @@ typedef intptr_t ssize_t;
int read_arg_or_stdin(const char *arg, unsigned char *buf, size_t buflen, size_t *written);
-bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize);
+bool hex_decode(const char *str, size_t *slen, void *buf, size_t bufsize);
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
#endif /* UTIL_H */