summaryrefslogtreecommitdiff
path: root/escaper.s
blob: 19b00959cd4928f1389c324488530e16ff36bab7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
global _start

%macro write 3
	mov rdi, %1
	mov rsi, %2
	mov rdx, %3
	mov rax, 1
	syscall
%endmacro

%macro read 3
	mov rdi, %1
	mov rsi, %2
	mov rdx, %3
	xor rax, rax
	syscall
%endmacro

%macro mmap 6
	mov rdi, %1
	mov rsi, %2
	mov rdx, %3
	mov r10, %4
	mov r8, %5
	mov r9, %6
	mov rax, 9
	syscall
%endmacro

%macro munmap 2
	mov rdi, %1
	mov rsi, %2
	mov rax, 11
	syscall
%endmacro

%macro exit 1
	mov rdi, %1
	mov rax, 60
	syscall
%endmacro

section .text
_start:
	pop qword [argc]
	pop rcx
	cmp dword [argc], 1
	jg skip_stdin
stdin_loop:
	read 0, buf, 4000
	cmp rax, 1
	jle end
	mov rdx, buf
	mov rcx, [argc]
	jmp count_start
clear_pos:
	cmp rbx, rax
	je arg_loop
	mov byte [pos + rax], 0
	inc rax
	jmp clear_pos
skip_stdin:
	mov rcx, [argc]
arg_loop:
	cmp rcx, 1
	jle end
	pop rdx
count_start:
	xor rax, rax
	xor rbx, rbx
count_loop:
	cmp byte [rdx + rax], '~'
	je found
	cmp byte [rdx + rax], '`'
	je found
	cmp byte [rdx + rax], '_'
	je found
	cmp byte [rdx + rax], '*'
	je found
	cmp byte [rdx + rax], '|'
	je found
	cmp byte [rdx + rax], '\'
	je found
	cmp byte [rdx + rax], 0
	je escape
	inc rax
	jmp count_loop
found:
	inc rbx
	mov byte [pos + rax], 1
	inc rax
	jmp count_loop
escape:
	push rcx ; argc counter
	push rax ; string length
	push rbx ; number of extra characters needed
	push rdx ; string memory address
	add rbx, rax
	inc rbx
	mmap 0, rbx, 3, 34, -1, 0	; 3 = PROT_READ | PROT_WRITE, 34 = MAP_PRIVATE | MAP_ANONYMOUS
	pop rdx
	pop rbx
	pop rsi
	add rsi, rbx
	xor r8, r8
	xor r9, r9
escape_loop:
	cmp r9, rsi
	je escape_loop_end
	cmp byte [pos + r8], 1
	jne skip_backslash
	mov byte [rax + r9], '\'
	inc r9
skip_backslash:
	mov r10b, byte [rdx + r8]
	mov byte [rax + r9], r10b
	inc r8
	inc r9
	jmp escape_loop
escape_loop_end:
	mov byte [rax + r9], 10
	inc r9
	push rax
	write 1, rax, r9
	pop rax
	munmap rax, r9
	pop rcx
next_arg:
	dec rcx
	xor rax, rax
	jmp clear_pos
end:
	exit 0

section .bss
	argc: resq 1
	buf: resb 4001
	pos: resb 4000