Some commands of `bitcoin-tx` accept an index of an existing input/output, e.g. `delin` or `delout`.  And while the index is checked for being out-of-bounds, garbage (non-numeral characters) are happily accepted.  All of the following are fine:

    $ bitcoin-tx -create outaddr=1:1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd delout=
    $ bitcoin-tx -create outaddr=1:1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd delout=foobar
    $ bitcoin-tx -create outaddr=1:1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd delout=0bla

I think all of them should throw an error instead of silently treating the index as zero.

The reason for this is that internally, `atoi` is called - and that by design discards anything after the first non-numeric character (and may just return zero if there are no numerals at all).

A possible fix would be to use `strtol` instead and to verify that the returned `endptr` is actually the end of the input string.  Alternatively, one could convert the integer back to a string and require that it matches the input string exactly.
char buf[4096];
        int bread = fread(buf, 1, sizeof(buf), f);
        if (bread <= 0)
            break;
        valStr.insert(valStr.size(), buf, bread);
    }
    int error = ferror(f);
    fclose(f);
    if (error) {
        std::string strErr = "Error reading file " + filename;
        throw std::runtime_error(strErr);
    }
    
    RegisterSetJson(key, valStr);
}
static CAmount ExtractAndValidateValue(const std::string& strValue)
{
    CAmount value;
    if (!ParseMoney(strValue, value))
        throw std::runtime_error("invalid TX output value");
    return value;
}
static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal)
{
    int64_t newVersion = atoi64(cmdVal);
    if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION)
        throw std::runtime_error("Invalid TX version requested");
    tx.nVersion = (int) newVersion;
}
static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal)