Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions SStream.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ void SStream_Init(SStream *ss)
ss->is_closed = false;
ss->markup_stream = false;
ss->prefixed_by_markup = false;
ss->unsigned_num = false;
}

void SStream_opt_unum(SStream *ss, bool print_unsigned_numbers)
{
assert(ss);
ss->unsigned_num = print_unsigned_numbers;
}

/// Returns the a pointer to the internal string buffer of the stream.
Expand Down Expand Up @@ -224,6 +231,10 @@ void SStream_concat(SStream *ss, const char *fmt, ...)
void printInt64Bang(SStream *ss, int64_t val)
{
assert(ss);
if (ss->unsigned_num) {
printUInt64Bang(ss, val);
return;
}
SSTREAM_RETURN_IF_CLOSED(ss);
SStream_concat1(ss, '#');
printInt64(ss, val);
Expand All @@ -241,6 +252,10 @@ void printUInt64Bang(SStream *ss, uint64_t val)
void printInt64(SStream *ss, int64_t val)
{
assert(ss);
if (ss->unsigned_num) {
printUInt64(ss, val);
return;
}
SSTREAM_RETURN_IF_CLOSED(ss);
if (val >= 0) {
if (val > HEX_THRESHOLD)
Expand Down Expand Up @@ -286,14 +301,40 @@ void printInt32BangDec(SStream *ss, int32_t val)
void printInt32Bang(SStream *ss, int32_t val)
{
assert(ss);
if (ss->unsigned_num) {
printUInt32Bang(ss, val);
return;
}
SSTREAM_RETURN_IF_CLOSED(ss);
SStream_concat1(ss, '#');
printInt32(ss, val);
}

void printUInt8(SStream *ss, uint8_t val)
{
assert(ss);
if (val > HEX_THRESHOLD)
SStream_concat(ss, "0x%"PRIx8, val);
else
SStream_concat(ss, "%"PRIu8, val);
}

void printUInt16(SStream *ss, uint16_t val)
{
assert(ss);
if (val > HEX_THRESHOLD)
SStream_concat(ss, "0x%"PRIx16, val);
else
SStream_concat(ss, "%"PRIu16, val);
}

void printInt8(SStream *ss, int8_t val)
{
assert(ss);
if (ss->unsigned_num) {
printUInt8(ss, val);
return;
}
SSTREAM_RETURN_IF_CLOSED(ss);
if (val >= 0) {
if (val > HEX_THRESHOLD)
Expand All @@ -314,6 +355,10 @@ void printInt8(SStream *ss, int8_t val)
void printInt16(SStream *ss, int16_t val)
{
assert(ss);
if (ss->unsigned_num) {
printUInt16(ss, val);
return;
}
SSTREAM_RETURN_IF_CLOSED(ss);
if (val >= 0) {
if (val > HEX_THRESHOLD)
Expand All @@ -334,6 +379,10 @@ void printInt16(SStream *ss, int16_t val)
void printInt16HexOffset(SStream *ss, int16_t val)
{
assert(ss);
if (ss->unsigned_num) {
printUInt16(ss, val);
return;
}
SSTREAM_RETURN_IF_CLOSED(ss);
if (val >= 0) {
SStream_concat(ss, "+0x%" PRIx16, val);
Expand All @@ -350,6 +399,10 @@ void printInt16HexOffset(SStream *ss, int16_t val)
void printInt32(SStream *ss, int32_t val)
{
assert(ss);
if (ss->unsigned_num) {
printUInt32(ss, val);
return;
}
SSTREAM_RETURN_IF_CLOSED(ss);
if (val >= 0) {
if (val > HEX_THRESHOLD)
Expand All @@ -371,6 +424,10 @@ void printInt32(SStream *ss, int32_t val)
void printInt32HexOffset(SStream *ss, int32_t val)
{
assert(ss);
if (ss->unsigned_num) {
printUInt32(ss, val);
return;
}
SSTREAM_RETURN_IF_CLOSED(ss);
if (val >= 0) {
SStream_concat(ss, "+0x%" PRIx32, val);
Expand Down
4 changes: 4 additions & 0 deletions SStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ typedef struct SStream {
bool is_closed;
bool markup_stream; ///< If true, markups to the stream are allowed.
bool prefixed_by_markup; ///< Set after the stream wrote a markup for an operand.
bool unsigned_num; ///< Print all numbers as unsigned. Set with CS_OPT_UNSIGNED.
} SStream;

#define SSTREAM_OVERFLOW_CHECK(OS, len) \
Expand All @@ -39,6 +40,7 @@ do { \
} while(0)

void SStream_Init(SStream *ss);
void SStream_opt_unum(SStream *ss, bool print_unsigned_numbers);

const char *SStream_replc(const SStream *ss, char elem, char repl);

Expand Down Expand Up @@ -81,6 +83,8 @@ void printInt32HexOffset(SStream *ss, int32_t val);

void printUInt32Bang(SStream *O, uint32_t val);

void printUInt8(SStream *ss, uint8_t val);
void printUInt16(SStream *ss, uint16_t val);
void printUInt32(SStream *O, uint32_t val);

// print number in decimal mode
Expand Down
2 changes: 2 additions & 0 deletions cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,7 @@ size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64

handle->insn_id(handle, insn_cache, mci.Opcode);

SStream_opt_unum(&ss, handle->imm_unsigned);
handle->printer(&mci, &ss, handle->printer_info);
fill_insn(handle, insn_cache, &ss, &mci, handle->post_printer, buffer);

Expand Down Expand Up @@ -1494,6 +1495,7 @@ bool CAPSTONE_API cs_disasm_iter(csh ud, const uint8_t **code, size_t *size,
// map internal instruction opcode to public insn ID
handle->insn_id(handle, insn, mci.Opcode);

SStream_opt_unum(&ss, handle->imm_unsigned);
handle->printer(&mci, &ss, handle->printer_info);

fill_insn(handle, insn, &ss, &mci, handle->post_printer, *code);
Expand Down
11 changes: 11 additions & 0 deletions tests/issues/issues.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6216,3 +6216,14 @@ test_cases:
insns:
- asm_text: "l32i.n a1, a3, 8"
illegal: -1

-
input:
name: "#2722 - CS_OPT_UNSIGNED is ignored for most archs"
bytes: [ 0x20, 0xf0, 0x5f, 0xf8 ]
arch: "CS_ARCH_AARCH64"
options: [ CS_OPT_UNSIGNED ]
address: 0x0
expected:
insns:
- asm_text: "ldur x0, [x1, #0xffffffffffffffff]"
83 changes: 83 additions & 0 deletions tests/unit/sstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,46 @@ bool test_printint64_bang()
return true;
}

bool test_printuint16()
{
printf("Test test_printuint16\n");

SStream OS = { 0 };
SStream_Init(&OS);
printUInt16(&OS, HEX_THRESHOLD + 1);
CHECK_OS_EQUAL_RET_FALSE(OS, "0xa");
SStream_Flush(&OS, NULL);

printUInt16(&OS, HEX_THRESHOLD);
CHECK_OS_EQUAL_RET_FALSE(OS, "9");
SStream_Flush(&OS, NULL);

printUInt16(&OS, UINT16_MAX);
CHECK_OS_EQUAL_RET_FALSE(OS, "0xffff");
SStream_Flush(&OS, NULL);
return true;
}

bool test_printuint8()
{
printf("Test test_printuint8\n");

SStream OS = { 0 };
SStream_Init(&OS);
printUInt8(&OS, HEX_THRESHOLD + 1);
CHECK_OS_EQUAL_RET_FALSE(OS, "0xa");
SStream_Flush(&OS, NULL);

printUInt8(&OS, HEX_THRESHOLD);
CHECK_OS_EQUAL_RET_FALSE(OS, "9");
SStream_Flush(&OS, NULL);

printUInt8(&OS, UINT8_MAX);
CHECK_OS_EQUAL_RET_FALSE(OS, "0xff");
SStream_Flush(&OS, NULL);
return true;
}

bool test_printuint32_bang()
{
printf("Test test_printuint32Bang\n");
Expand Down Expand Up @@ -349,6 +389,46 @@ bool test_trimls() {
return true;
}

bool test_stream_unsigned_imm()
{
printf("Test test_stream_unsigned_imm\n");

SStream OS = { 0 };
SStream_Init(&OS);

OS.unsigned_num = true;
printInt8(&OS, -1);
CHECK_OS_EQUAL_RET_FALSE(OS, "0xff");
SStream_Flush(&OS, NULL);

OS.unsigned_num = true;
printInt16(&OS, -1);
CHECK_OS_EQUAL_RET_FALSE(OS, "0xffff");
SStream_Flush(&OS, NULL);

OS.unsigned_num = true;
printInt32(&OS, -1);
CHECK_OS_EQUAL_RET_FALSE(OS, "0xffffffff");
SStream_Flush(&OS, NULL);

OS.unsigned_num = true;
printInt32Bang(&OS, -1);
CHECK_OS_EQUAL_RET_FALSE(OS, "#0xffffffff");
SStream_Flush(&OS, NULL);


OS.unsigned_num = true;
printInt64(&OS, -1);
CHECK_OS_EQUAL_RET_FALSE(OS, "0xffffffffffffffff");
SStream_Flush(&OS, NULL);

OS.unsigned_num = true;
printInt64Bang(&OS, -1);
CHECK_OS_EQUAL_RET_FALSE(OS, "#0xffffffffffffffff");
SStream_Flush(&OS, NULL);
return true;
}

bool test_copy_mnem_opstr() {
printf("Test test_copy_mnem_opstr\n");

Expand Down Expand Up @@ -519,8 +599,11 @@ int main()
result &= test_printint64();
result &= test_printint32_bang();
result &= test_printint64_bang();
result &= test_printuint8();
result &= test_printuint16();
result &= test_printuint32_bang();
result &= test_printuint64_bang();
result &= test_stream_unsigned_imm();
result &= test_replc();
result &= test_replc_str();
result &= test_copy_mnem_opstr();
Expand Down
Loading