Skip to content

Commit 1610dc8

Browse files
committed
Add more string rules
1 parent 4a98e6e commit 1610dc8

8 files changed

Lines changed: 1020 additions & 0 deletions

File tree

rules/cstring/ir_unsafe.json

Lines changed: 498 additions & 0 deletions
Large diffs are not rendered by default.

rules/cstring/src.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4+
#define _GNU_SOURCE
45
#include <string.h>
6+
#include <strings.h>
57

68
void *f1(void *dst, const void *src, size_t n) { return memcpy(dst, src, n); }
79

@@ -24,3 +26,15 @@ void *f10(const void *a0, int a1, size_t a2) { return memchr(a0, a1, a2); }
2426
char *f11(const char *a0, int a1) { return strrchr(a0, a1); }
2527

2628
char *f15(const char *a0) { return strdup(a0); }
29+
30+
size_t f16(const char *a0, const char *a1) { return strcspn(a0, a1); }
31+
32+
size_t f17(const char *a0, const char *a1) { return strspn(a0, a1); }
33+
34+
char *f18(const char *a0, const char *a1) { return strstr(a0, a1); }
35+
36+
char *f21(const char *a0, const char *a1) { return strpbrk(a0, a1); }
37+
38+
void *f24(const void *a0, int a1, size_t a2) { return memrchr(a0, a1, a2); }
39+
40+
int f27(const char *a0, const char *a1) { return strcasecmp(a0, a1); }

rules/cstring/src.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4+
#define _GNU_SOURCE
45
#include <string.h>
56

67
const char *f6(const char *a0, int a1) { return strchr(a0, a1); }
8+
9+
const void *f12(const void *a0, int a1, size_t a2) { return memchr(a0, a1, a2); }
10+
11+
const char *f13(const char *a0, int a1) { return strrchr(a0, a1); }
12+
13+
char *f14(char *a0, int a1) { return strrchr(a0, a1); }
14+
15+
const char *f19(const char *a0, const char *a1) { return strstr(a0, a1); }
16+
17+
char *f20(char *a0, const char *a1) { return strstr(a0, a1); }
18+
19+
const char *f22(const char *a0, const char *a1) { return strpbrk(a0, a1); }
20+
21+
char *f23(char *a0, const char *a1) { return strpbrk(a0, a1); }
22+
23+
const void *f25(const void *a0, int a1, size_t a2) { return memrchr(a0, a1, a2); }
24+
25+
void *f26(void *a0, int a1, size_t a2) { return memrchr(a0, a1, a2); }

rules/cstring/tgt_unsafe.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,51 @@ unsafe fn f14(a0: *mut u8, a1: i32) -> *mut u8 {
7979
unsafe fn f15(a0: *const u8) -> *mut u8 {
8080
libc::strdup(a0 as *const i8) as *mut u8
8181
}
82+
83+
unsafe fn f16(a0: *const u8, a1: *const u8) -> u64 {
84+
libc::strcspn(a0 as *const i8, a1 as *const i8) as u64
85+
}
86+
87+
unsafe fn f17(a0: *const u8, a1: *const u8) -> u64 {
88+
libc::strspn(a0 as *const i8, a1 as *const i8) as u64
89+
}
90+
91+
unsafe fn f18(a0: *const u8, a1: *const u8) -> *mut u8 {
92+
libc::strstr(a0 as *const i8, a1 as *const i8) as *mut u8
93+
}
94+
95+
unsafe fn f19(a0: *const u8, a1: *const u8) -> *const u8 {
96+
libc::strstr(a0 as *const i8, a1 as *const i8) as *const u8
97+
}
98+
99+
unsafe fn f20(a0: *mut u8, a1: *const u8) -> *mut u8 {
100+
libc::strstr(a0 as *const i8, a1 as *const i8) as *mut u8
101+
}
102+
103+
unsafe fn f21(a0: *const u8, a1: *const u8) -> *mut u8 {
104+
libc::strpbrk(a0 as *const i8, a1 as *const i8) as *mut u8
105+
}
106+
107+
unsafe fn f22(a0: *const u8, a1: *const u8) -> *const u8 {
108+
libc::strpbrk(a0 as *const i8, a1 as *const i8) as *const u8
109+
}
110+
111+
unsafe fn f23(a0: *mut u8, a1: *const u8) -> *mut u8 {
112+
libc::strpbrk(a0 as *const i8, a1 as *const i8) as *mut u8
113+
}
114+
115+
unsafe fn f24(a0: *const u8, a1: i32, a2: usize) -> *mut ::libc::c_void {
116+
libc::memrchr(a0 as *const ::libc::c_void, a1, a2 as usize)
117+
}
118+
119+
unsafe fn f25(a0: *const u8, a1: i32, a2: usize) -> *const ::libc::c_void {
120+
libc::memrchr(a0 as *const ::libc::c_void, a1, a2 as usize) as *const ::libc::c_void
121+
}
122+
123+
unsafe fn f26(a0: *mut u8, a1: i32, a2: usize) -> *mut ::libc::c_void {
124+
libc::memrchr(a0 as *const ::libc::c_void, a1, a2 as usize)
125+
}
126+
127+
unsafe fn f27(a0: *const u8, a1: *const u8) -> i32 {
128+
libc::strcasecmp(a0 as *const i8, a1 as *const i8)
129+
}

tests/unit/cstring.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// no-compile: refcount
2+
#define _GNU_SOURCE
23
#include <cassert>
34
#include <cstdlib>
45
#include <cstring>
6+
#include <strings.h>
57

68
static void test_memcpy() {
79
const char src[] = "hello";
@@ -113,6 +115,63 @@ static void test_strdup() {
113115
std::free(d3);
114116
}
115117

118+
static void test_strcspn() {
119+
assert(std::strcspn("hello", "el") == 1);
120+
assert(std::strcspn("abc", "xyz") == 3);
121+
assert(std::strcspn("", "abc") == 0);
122+
const char *s = "hello";
123+
const char *rej = "el";
124+
assert(std::strcspn(s, rej) == 1);
125+
}
126+
127+
static void test_strspn() {
128+
assert(std::strspn("hello", "hel") == 4);
129+
assert(std::strspn("abc", "xyz") == 0);
130+
assert(std::strspn("aaa", "a") == 3);
131+
const char *s = "hello";
132+
const char *acc = "hel";
133+
assert(std::strspn(s, acc) == 4);
134+
}
135+
136+
static void test_strstr() {
137+
const char *h = "hello world";
138+
const char *r = std::strstr(h, "world");
139+
assert(r != nullptr);
140+
assert(r == h + 6);
141+
assert(std::strstr(h, "xyz") == nullptr);
142+
char buf[] = {'h', 'e', 'l', 'l', 'o', '\0'};
143+
assert(std::strstr(buf, "ll") == &buf[2]);
144+
}
145+
146+
static void test_strpbrk() {
147+
const char *s = "hello world";
148+
const char *r = std::strpbrk(s, "wo");
149+
assert(r != nullptr);
150+
assert(r == s + 4);
151+
assert(std::strpbrk(s, "xyz") == nullptr);
152+
char buf[] = {'a', 'b', 'c', '\0'};
153+
assert(std::strpbrk(buf, "b") == &buf[1]);
154+
}
155+
156+
static void test_memrchr() {
157+
const char data[] = {1, 2, 3, 2, 4};
158+
const void *r = memrchr(data, 2, 5);
159+
assert(r == &data[3]);
160+
assert(memrchr(data, 99, 5) == nullptr);
161+
const void *p = data;
162+
std::size_t n = 5;
163+
assert(memrchr(p, 1, n) == p);
164+
}
165+
166+
static void test_strcasecmp() {
167+
assert(strcasecmp("HELLO", "hello") == 0);
168+
assert(strcasecmp("abc", "abd") < 0);
169+
assert(strcasecmp("abd", "abc") > 0);
170+
const char *p = "FOO";
171+
const char *q = "foo";
172+
assert(strcasecmp(p, q) == 0);
173+
}
174+
116175
int main() {
117176
test_memcpy();
118177
test_memset();
@@ -125,5 +184,11 @@ int main() {
125184
test_memchr();
126185
test_strrchr();
127186
test_strdup();
187+
test_strcspn();
188+
test_strspn();
189+
test_strstr();
190+
test_strpbrk();
191+
test_memrchr();
192+
test_strcasecmp();
128193
return 0;
129194
}

tests/unit/out/unsafe/cstring.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,129 @@ pub unsafe fn test_strdup_10() {
292292
);
293293
libc::free((d3 as *mut u8 as *mut ::libc::c_void));
294294
}
295+
pub unsafe fn test_strcspn_11() {
296+
assert!(
297+
((libc::strcspn(
298+
b"hello\0".as_ptr() as *const i8,
299+
b"el\0".as_ptr() as *const i8
300+
) as u64)
301+
== (1_u64))
302+
);
303+
assert!(
304+
((libc::strcspn(
305+
b"abc\0".as_ptr() as *const i8,
306+
b"xyz\0".as_ptr() as *const i8
307+
) as u64)
308+
== (3_u64))
309+
);
310+
assert!(
311+
((libc::strcspn(b"\0".as_ptr() as *const i8, b"abc\0".as_ptr() as *const i8) as u64)
312+
== (0_u64))
313+
);
314+
let mut s: *const u8 = b"hello\0".as_ptr();
315+
let mut rej: *const u8 = b"el\0".as_ptr();
316+
assert!(((libc::strcspn(s as *const i8, rej as *const i8) as u64) == (1_u64)));
317+
}
318+
pub unsafe fn test_strspn_12() {
319+
assert!(
320+
((libc::strspn(
321+
b"hello\0".as_ptr() as *const i8,
322+
b"hel\0".as_ptr() as *const i8
323+
) as u64)
324+
== (4_u64))
325+
);
326+
assert!(
327+
((libc::strspn(
328+
b"abc\0".as_ptr() as *const i8,
329+
b"xyz\0".as_ptr() as *const i8
330+
) as u64)
331+
== (0_u64))
332+
);
333+
assert!(
334+
((libc::strspn(b"aaa\0".as_ptr() as *const i8, b"a\0".as_ptr() as *const i8) as u64)
335+
== (3_u64))
336+
);
337+
let mut s: *const u8 = b"hello\0".as_ptr();
338+
let mut acc: *const u8 = b"hel\0".as_ptr();
339+
assert!(((libc::strspn(s as *const i8, acc as *const i8) as u64) == (4_u64)));
340+
}
341+
pub unsafe fn test_strstr_13() {
342+
let mut h: *const u8 = b"hello world\0".as_ptr();
343+
let mut r: *const u8 =
344+
libc::strstr(h as *const i8, b"world\0".as_ptr() as *const i8) as *const u8;
345+
assert!(!((r).is_null()));
346+
assert!(((r) == (h.offset((6) as isize))));
347+
assert!((libc::strstr(h as *const i8, b"xyz\0".as_ptr() as *const i8) as *const u8).is_null());
348+
let mut buf: [u8; 6] = [
349+
('h' as u8),
350+
('e' as u8),
351+
('l' as u8),
352+
('l' as u8),
353+
('o' as u8),
354+
('\0' as u8),
355+
];
356+
assert!(
357+
((libc::strstr(buf.as_mut_ptr() as *const i8, b"ll\0".as_ptr() as *const i8) as *mut u8)
358+
== (&mut buf[(2) as usize] as *mut u8))
359+
);
360+
}
361+
pub unsafe fn test_strpbrk_14() {
362+
let mut s: *const u8 = b"hello world\0".as_ptr();
363+
let mut r: *const u8 =
364+
libc::strpbrk(s as *const i8, b"wo\0".as_ptr() as *const i8) as *const u8;
365+
assert!(!((r).is_null()));
366+
assert!(((r) == (s.offset((4) as isize))));
367+
assert!((libc::strpbrk(s as *const i8, b"xyz\0".as_ptr() as *const i8) as *const u8).is_null());
368+
let mut buf: [u8; 4] = [('a' as u8), ('b' as u8), ('c' as u8), ('\0' as u8)];
369+
assert!(
370+
((libc::strpbrk(buf.as_mut_ptr() as *const i8, b"b\0".as_ptr() as *const i8) as *mut u8)
371+
== (&mut buf[(1) as usize] as *mut u8))
372+
);
373+
}
374+
pub unsafe fn test_memrchr_15() {
375+
let data: [u8; 5] = [1_u8, 2_u8, 3_u8, 2_u8, 4_u8];
376+
let mut r: *const ::libc::c_void = libc::memrchr(
377+
(data.as_ptr() as *const u8 as *const ::libc::c_void) as *const ::libc::c_void,
378+
2,
379+
5_u64 as usize,
380+
) as *const ::libc::c_void;
381+
assert!(((r) == ((&data[(3) as usize] as *const u8) as *const u8 as *const ::libc::c_void)));
382+
assert!((libc::memrchr(
383+
(data.as_ptr() as *const u8 as *const ::libc::c_void) as *const ::libc::c_void,
384+
99,
385+
5_u64 as usize
386+
) as *const ::libc::c_void)
387+
.is_null());
388+
let mut p: *const ::libc::c_void = (data.as_ptr() as *const u8 as *const ::libc::c_void);
389+
let mut n: u64 = 5_u64;
390+
assert!(
391+
((libc::memrchr(p as *const ::libc::c_void, 1, n as usize) as *const ::libc::c_void)
392+
== (p))
393+
);
394+
}
395+
pub unsafe fn test_strcasecmp_16() {
396+
assert!(
397+
((libc::strcasecmp(
398+
b"HELLO\0".as_ptr() as *const i8,
399+
b"hello\0".as_ptr() as *const i8
400+
)) == (0))
401+
);
402+
assert!(
403+
((libc::strcasecmp(
404+
b"abc\0".as_ptr() as *const i8,
405+
b"abd\0".as_ptr() as *const i8
406+
)) < (0))
407+
);
408+
assert!(
409+
((libc::strcasecmp(
410+
b"abd\0".as_ptr() as *const i8,
411+
b"abc\0".as_ptr() as *const i8
412+
)) > (0))
413+
);
414+
let mut p: *const u8 = b"FOO\0".as_ptr();
415+
let mut q: *const u8 = b"foo\0".as_ptr();
416+
assert!(((libc::strcasecmp(p as *const i8, q as *const i8)) == (0)));
417+
}
295418
pub fn main() {
296419
unsafe {
297420
std::process::exit(main_0() as i32);
@@ -309,5 +432,11 @@ unsafe fn main_0() -> i32 {
309432
(unsafe { test_memchr_8() });
310433
(unsafe { test_strrchr_9() });
311434
(unsafe { test_strdup_10() });
435+
(unsafe { test_strcspn_11() });
436+
(unsafe { test_strspn_12() });
437+
(unsafe { test_strstr_13() });
438+
(unsafe { test_strpbrk_14() });
439+
(unsafe { test_memrchr_15() });
440+
(unsafe { test_strcasecmp_16() });
312441
return 0;
313442
}

0 commit comments

Comments
 (0)