-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Attasm #25028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements AT&T to Intel syntax conversion for x86 assembly in radare2. The implementation extracts and refactors the conversion logic into a reusable utility function, enabling assembly operations to automatically convert AT&T syntax to Intel when needed.
Key changes:
- Adds a new shared AT&T to Intel converter in
libr/util/str_att.cwith comprehensive instruction coverage - Refactors the existing
att2intelplugin to use the new shared implementation - Integrates automatic syntax conversion in the assembler when AT&T syntax is specified but encoders only support Intel
- Adds comprehensive test coverage with 35+ test cases covering various x86 instructions and edge cases
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
libr/util/str_att.c |
New implementation of AT&T to Intel syntax converter with instruction tables and conversion logic |
libr/arch/p/x86_nz/att2intel.c |
Refactored to delegate to the shared r_str_att2intel() function |
libr/asm/asm.c |
Integration of automatic syntax conversion in assembly process with arch-specific checks |
libr/include/r_util/r_str.h |
API declaration for r_str_att2intel() |
libr/include/r_asm.h |
API declaration for r_asm_att2intel() wrapper |
libr/include/r_arch.h |
New constants and bitmasks for encoder syntax support |
libr/util/meson.build |
Added str_att.c to meson build |
libr/util/Makefile |
Added str_att.o to makefile build |
test/db/cmd/attasm |
Comprehensive test suite with 35+ tests for AT&T syntax conversion |
test/db/cmd/cmd_asm_syntax |
Empty placeholder test file |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| while (start > buf && (isdigit ((unsigned char)*(start - 1)) || *(start - 1) == '-' || *(start - 1) == '+')) { | ||
| start--; | ||
| } | ||
| if (start < ptr && start > buf && *(start - 1) != ' ' && *(start - 1) != ',') { | ||
| // skip this case, it's part of an operand name | ||
| } else if (start < ptr) { | ||
| // there's a displacement | ||
| int disp = atoi (start); |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function uses 'isdigit' to detect displacement values, but this won't correctly handle hexadecimal values like '0x10' in AT&T syntax. When the code checks for digits before the bracket at line 252, it will only match decimal digits. For hex values like '0x10[rbp]', the 'x' character will stop the backward scan prematurely. Consider supporting hexadecimal displacement values or documenting this limitation.
| while (start > buf && (isdigit ((unsigned char)*(start - 1)) || *(start - 1) == '-' || *(start - 1) == '+')) { | |
| start--; | |
| } | |
| if (start < ptr && start > buf && *(start - 1) != ' ' && *(start - 1) != ',') { | |
| // skip this case, it's part of an operand name | |
| } else if (start < ptr) { | |
| // there's a displacement | |
| int disp = atoi (start); | |
| while (start > buf) { | |
| char c = *(start - 1); | |
| if (isdigit((unsigned char)c) || c == '-' || c == '+' || | |
| (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || | |
| c == 'x' || c == 'X') { | |
| start--; | |
| } else { | |
| break; | |
| } | |
| } | |
| if (start < ptr && start > buf && *(start - 1) != ' ' && *(start - 1) != ',') { | |
| // skip this case, it's part of an operand name | |
| } else if (start < ptr) { | |
| // there's a displacement | |
| int disp = (int)strtol(start, NULL, 0); |
| } | ||
|
|
||
| // skip directives and labels | ||
| if (*buf == '.' || (strlen (buf) > 0 && buf[strlen (buf) - 1] == ':')) { |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When checking 'strlen(buf) > 0' at line 232, this is redundant since if '*buf' is checked first with the condition '*buf == '.'', then 'strlen(buf)' must be > 0. The condition could be simplified to just checking if 'buf[strlen(buf) - 1] == ':''. However, consider that calling 'strlen' twice (once for comparison, once for indexing) is inefficient. Store the length in a variable or use a pointer to check the last character.
| if (*buf == '.' || (strlen (buf) > 0 && buf[strlen (buf) - 1] == ':')) { | |
| size_t len = strlen (buf); | |
| if (*buf == '.' || (len > 0 && buf[len - 1] == ':')) { |
| if (argc >= 2 && (is_in_list (argv[0], ops_1) || is_in_list (op, ops_1))) { | ||
| // 1 operand instruction | ||
| if (newstr) { | ||
| snprintf (newstr, 256, "%s %s", op, argv[1]); |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function uses hardcoded buffer size 256 for snprintf calls, but allocates the buffer with strlen(att_str) + 256 on line 356. If the operands are long (especially memory addressing expressions), the snprintf calls could exceed 256 bytes. Consider using a consistent buffer size calculation or using the actual allocated size.
|
|
||
| // no operands fallback | ||
| if (argc == 1 && newstr) { | ||
| strcpy (newstr, op); |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using strcpy without bounds checking. Although 'op' is limited to 32 bytes and 'newstr' is allocated with strlen(att_str) + 256 on line 356, it's safer to use a bounds-checked copy function like strncpy or verify the size explicitly.
| if (is_in_list (argv[0], ops_0) || is_in_list (op, ops_0)) { | ||
| // 0 operand instruction | ||
| if (newstr) { | ||
| strcpy (newstr, op); |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using strcpy without bounds checking. Although 'op' is limited to 32 bytes and 'newstr' is allocated with strlen(att_str) + 256 on line 356, it's safer to use a bounds-checked copy function like strncpy or verify the size explicitly.
| // rebuild: [inner+disp]rest | ||
| size_t avail = strlen (att_str) + 64 - (start - buf); | ||
| snprintf (start, avail, "[%s%+d]%s", inner, disp, rest ? rest : ""); |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If 'strdup(close + 1)' fails and returns NULL on line 269, the code continues and passes 'rest ? rest : ""' to snprintf. While this prevents a crash, if strdup failed due to memory pressure, the subsequent malloc on line 356 might also fail. Consider checking for allocation failures and returning early to avoid inconsistent state.
| // rebuild: [inner+disp]rest | |
| size_t avail = strlen (att_str) + 64 - (start - buf); | |
| snprintf (start, avail, "[%s%+d]%s", inner, disp, rest ? rest : ""); | |
| if (!rest) { | |
| free (buf); | |
| return NULL; | |
| } | |
| // rebuild: [inner+disp]rest | |
| size_t avail = strlen (att_str) + 64 - (start - buf); | |
| snprintf (start, avail, "[%s%+d]%s", inner, disp, rest); |
| if (argc >= 3 && (is_in_list (argv[0], ops_2swap) || is_in_list (op, ops_2swap))) { | ||
| // 2 operand instruction - swap operands (ATT: src, dst -> Intel: dst, src) | ||
| if (newstr) { | ||
| snprintf (newstr, 256, "%s %s, %s", op, argv[2], argv[1]); |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function uses hardcoded buffer size 256 for snprintf calls, but allocates the buffer with strlen(att_str) + 256 on line 356. If the operands are long (especially memory addressing expressions), the snprintf calls could exceed 256 bytes. Consider using a consistent buffer size calculation or using the actual allocated size.
| snprintf (newstr, 256, "%s %s, %s", op, argv[2], argv[1]); | ||
| return true; | ||
| } | ||
|
|
||
| // single operand fallback | ||
| if (argc == 2 && newstr) { | ||
| snprintf (newstr, 256, "%s %s", op, argv[1]); |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function uses hardcoded buffer size 256 for snprintf calls, but allocates the buffer with strlen(att_str) + 256 on line 356. If the operands are long (especially memory addressing expressions), the snprintf calls could exceed 256 bytes. Consider using a consistent buffer size calculation or using the actual allocated size.
| size_t avail = strlen (att_str) + 64 - (start - buf); | ||
| snprintf (start, avail, "[%s%+d]%s", inner, disp, rest ? rest : ""); |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The buffer size calculation is incorrect. 'avail' is computed as strlen(att_str) + 64 - (start - buf), but 'buf' may have been modified (characters replaced) so its length may be different from att_str. The available space should be based on the actual allocated size of 'buf' or the remaining space from 'start' to the end of 'buf'. This could lead to buffer overflow.
| @@ -0,0 +1 @@ | |||
|
|
|||
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test file appears to be empty (contains only whitespace). If this is intentional as a placeholder, consider either removing it or adding a comment explaining its purpose. Empty test files can be confusing for maintainers.
| # This file is intentionally left empty as a placeholder for future tests. |
Description