Skip to content

Commit c9dae5e

Browse files
authored
[unsafe] Add more string.h rules (#125)
1 parent f4ba247 commit c9dae5e

12 files changed

Lines changed: 2342 additions & 86 deletions

File tree

rules/cstring/ir_unsafe.json

Lines changed: 874 additions & 20 deletions
Large diffs are not rendered by default.

rules/cstring/src.c

Lines changed: 28 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

@@ -12,3 +14,29 @@ int f3(const void *s1, const void *s2, size_t n) { return memcmp(s1, s2, n); }
1214
void *f4(void *dst, const void *src, size_t n) { return memmove(dst, src, n); }
1315

1416
char *f5(const char *a0, int a1) { return strchr(a0, a1); }
17+
18+
size_t f7(const char *a0) { return strlen(a0); }
19+
20+
int f8(const char *a0, const char *a1) { return strcmp(a0, a1); }
21+
22+
int f9(const char *a0, const char *a1, size_t a2) { return strncmp(a0, a1, a2); }
23+
24+
void *f10(const void *a0, int a1, size_t a2) { return memchr(a0, a1, a2); }
25+
26+
char *f11(const char *a0, int a1) { return strrchr(a0, a1); }
27+
28+
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+
#if defined(__linux__)
39+
void *f24(const void *a0, int a1, size_t a2) { return memrchr(a0, a1, a2); }
40+
#endif
41+
42+
int f27(const char *a0, const char *a1) { return strcasecmp(a0, a1); }

rules/cstring/src.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,23 @@
44
#include <string.h>
55

66
const char *f6(const char *a0, int a1) { return strchr(a0, a1); }
7+
8+
const void *f12(const void *a0, int a1, size_t a2) { return memchr(a0, a1, a2); }
9+
10+
const char *f13(const char *a0, int a1) { return strrchr(a0, a1); }
11+
12+
char *f14(char *a0, int a1) { return strrchr(a0, a1); }
13+
14+
const char *f19(const char *a0, const char *a1) { return strstr(a0, a1); }
15+
16+
char *f20(char *a0, const char *a1) { return strstr(a0, a1); }
17+
18+
const char *f22(const char *a0, const char *a1) { return strpbrk(a0, a1); }
19+
20+
char *f23(char *a0, const char *a1) { return strpbrk(a0, a1); }
21+
22+
#if defined(__linux__)
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); }
26+
#endif

rules/cstring/tgt_unsafe.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,90 @@ unsafe fn f5(a0: *const u8, a1: i32) -> *mut u8 {
4343
unsafe fn f6(a0: *const u8, a1: i32) -> *const u8 {
4444
libc::strchr(a0 as *const i8, a1) as *const u8
4545
}
46+
47+
unsafe fn f7(a0: *const u8) -> u64 {
48+
libc::strlen(a0 as *const i8) as u64
49+
}
50+
51+
unsafe fn f8(a0: *const u8, a1: *const u8) -> i32 {
52+
libc::strcmp(a0 as *const i8, a1 as *const i8)
53+
}
54+
55+
unsafe fn f9(a0: *const u8, a1: *const u8, a2: usize) -> i32 {
56+
libc::strncmp(a0 as *const i8, a1 as *const i8, a2 as usize)
57+
}
58+
59+
unsafe fn f10(a0: *const u8, a1: i32, a2: usize) -> *mut ::libc::c_void {
60+
libc::memchr(a0 as *const ::libc::c_void, a1, a2 as usize)
61+
}
62+
63+
unsafe fn f11(a0: *const u8, a1: i32) -> *mut u8 {
64+
libc::strrchr(a0 as *const i8, a1) as *mut u8
65+
}
66+
67+
unsafe fn f12(a0: *const u8, a1: i32, a2: usize) -> *const ::libc::c_void {
68+
libc::memchr(a0 as *const ::libc::c_void, a1, a2 as usize) as *const ::libc::c_void
69+
}
70+
71+
unsafe fn f13(a0: *const u8, a1: i32) -> *const u8 {
72+
libc::strrchr(a0 as *const i8, a1) as *const u8
73+
}
74+
75+
unsafe fn f14(a0: *mut u8, a1: i32) -> *mut u8 {
76+
libc::strrchr(a0 as *const i8, a1) as *mut u8
77+
}
78+
79+
unsafe fn f15(a0: *const u8) -> *mut u8 {
80+
libc::strdup(a0 as *const i8) as *mut u8
81+
}
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+
#[cfg(target_os = "linux")]
116+
unsafe fn f24(a0: *const u8, a1: i32, a2: usize) -> *mut ::libc::c_void {
117+
libc::memrchr(a0 as *const ::libc::c_void, a1, a2 as usize)
118+
}
119+
120+
#[cfg(target_os = "linux")]
121+
unsafe fn f25(a0: *const u8, a1: i32, a2: usize) -> *const ::libc::c_void {
122+
libc::memrchr(a0 as *const ::libc::c_void, a1, a2 as usize) as *const ::libc::c_void
123+
}
124+
125+
#[cfg(target_os = "linux")]
126+
unsafe fn f26(a0: *mut u8, a1: i32, a2: usize) -> *mut ::libc::c_void {
127+
libc::memrchr(a0 as *const ::libc::c_void, a1, a2 as usize)
128+
}
129+
130+
unsafe fn f27(a0: *const u8, a1: *const u8) -> i32 {
131+
libc::strcasecmp(a0 as *const i8, a1 as *const i8)
132+
}

tests/unit/cstring.cpp

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
// no-compile: refcount
2+
#define _GNU_SOURCE
3+
#include <cassert>
4+
#include <cstdlib>
5+
#include <cstring>
6+
#include <strings.h>
7+
8+
static void test_memcpy() {
9+
const char src[] = "hello";
10+
char dst[6] = {0};
11+
void *r = std::memcpy(dst, src, 6);
12+
assert(r == dst);
13+
assert(dst[0] == 'h' && dst[1] == 'e' && dst[2] == 'l');
14+
assert(dst[3] == 'l' && dst[4] == 'o' && dst[5] == '\0');
15+
}
16+
17+
static void test_memset() {
18+
char buf[4];
19+
void *r = std::memset(buf, 'x', 4);
20+
assert(r == buf);
21+
assert(buf[0] == 'x' && buf[1] == 'x' && buf[2] == 'x' && buf[3] == 'x');
22+
}
23+
24+
static void test_memcmp() {
25+
const char a[] = {1, 2, 3, 4};
26+
const char b[] = {1, 2, 3, 4};
27+
const char c[] = {1, 2, 9, 4};
28+
assert(std::memcmp(a, b, 4) == 0);
29+
assert(std::memcmp(a, c, 4) < 0);
30+
assert(std::memcmp(c, a, 4) > 0);
31+
}
32+
33+
static void test_memmove() {
34+
char buf[6] = {'a', 'b', 'c', 'd', 'e', '\0'};
35+
void *r = std::memmove(buf + 1, buf, 4);
36+
assert(r == buf + 1);
37+
assert(buf[0] == 'a' && buf[1] == 'a' && buf[2] == 'b');
38+
assert(buf[3] == 'c' && buf[4] == 'd' && buf[5] == '\0');
39+
}
40+
41+
static void test_strchr() {
42+
const char *s = "hello world";
43+
const char *r = std::strchr(s, 'w');
44+
assert(r != nullptr);
45+
assert(*r == 'w');
46+
assert(std::strchr(s, 'z') == nullptr);
47+
}
48+
49+
static void test_strlen() {
50+
assert(std::strlen("") == 0);
51+
assert(std::strlen("hello") == 5);
52+
assert(std::strlen("hello world") == 11);
53+
}
54+
55+
static void test_strcmp() {
56+
assert(std::strcmp("abc", "abc") == 0);
57+
assert(std::strcmp("abc", "abd") < 0);
58+
assert(std::strcmp("abd", "abc") > 0);
59+
const char *p = "abc";
60+
const char *q = "abd";
61+
char buf[] = {'a', 'b', 'c', '\0'};
62+
assert(std::strcmp(p, p) == 0);
63+
assert(std::strcmp(p, q) < 0);
64+
assert(std::strcmp(buf, p) == 0);
65+
}
66+
67+
static void test_strncmp() {
68+
assert(std::strncmp("abcdef", "abcxyz", 3) == 0);
69+
assert(std::strncmp("abcdef", "abcxyz", 4) < 0);
70+
assert(std::strncmp("abcxyz", "abcdef", 4) > 0);
71+
const char *p = "abcdef";
72+
const char *q = "abcxyz";
73+
char buf[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
74+
std::size_t n = 3;
75+
assert(std::strncmp(p, q, n) == 0);
76+
assert(std::strncmp(p, q, n + 1) < 0);
77+
assert(std::strncmp(buf, p, 6) == 0);
78+
}
79+
80+
static void test_memchr() {
81+
const char data[] = {0x10, 0x20, 0x30, 0x40};
82+
const void *r = std::memchr(data, 0x30, 4);
83+
assert(r == &data[2]);
84+
assert(std::memchr(data, 0x99, 4) == nullptr);
85+
const void *p = data;
86+
std::size_t n = 4;
87+
assert(std::memchr(p, 0x10, n) == p);
88+
}
89+
90+
static void test_strrchr() {
91+
const char *s = "hello world";
92+
const char *r = std::strrchr(s, 'l');
93+
assert(r != nullptr);
94+
assert(*r == 'l');
95+
assert(r == s + 9);
96+
assert(std::strrchr(s, 'z') == nullptr);
97+
char buf[] = {'a', 'b', 'a', '\0'};
98+
assert(std::strrchr(buf, 'a') == &buf[2]);
99+
}
100+
101+
static void test_strdup() {
102+
char *d = strdup("hello");
103+
assert(d != nullptr);
104+
assert(std::strcmp(d, "hello") == 0);
105+
std::free(d);
106+
const char *p = "world";
107+
char buf[] = {'a', 'b', 'c', '\0'};
108+
char *d2 = strdup(p);
109+
assert(d2 != nullptr);
110+
assert(std::strcmp(d2, p) == 0);
111+
std::free(d2);
112+
char *d3 = strdup(buf);
113+
assert(d3 != nullptr);
114+
assert(std::strcmp(d3, buf) == 0);
115+
std::free(d3);
116+
}
117+
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_strcasecmp() {
157+
assert(strcasecmp("HELLO", "hello") == 0);
158+
assert(strcasecmp("abc", "abd") < 0);
159+
assert(strcasecmp("abd", "abc") > 0);
160+
const char *p = "FOO";
161+
const char *q = "foo";
162+
assert(strcasecmp(p, q) == 0);
163+
}
164+
165+
int main() {
166+
test_memcpy();
167+
test_memset();
168+
test_memcmp();
169+
test_memmove();
170+
test_strchr();
171+
test_strlen();
172+
test_strcmp();
173+
test_strncmp();
174+
test_memchr();
175+
test_strrchr();
176+
test_strdup();
177+
test_strcspn();
178+
test_strspn();
179+
test_strstr();
180+
test_strpbrk();
181+
test_strcasecmp();
182+
return 0;
183+
}

0 commit comments

Comments
 (0)