Skip to content

Commit b632c50

Browse files
committed
Add strncmp/strcmp rules + tests
1 parent 158b38f commit b632c50

7 files changed

Lines changed: 327 additions & 0 deletions

File tree

rules/cstring/ir_unsafe.json

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,5 +413,93 @@
413413
"return_type": {
414414
"type": "u64"
415415
}
416+
},
417+
"f8": {
418+
"body": [
419+
{
420+
"text": "libc::strcmp("
421+
},
422+
{
423+
"placeholder": {
424+
"arg": 0,
425+
"access": "read"
426+
}
427+
},
428+
{
429+
"text": " as *const i8, "
430+
},
431+
{
432+
"placeholder": {
433+
"arg": 1,
434+
"access": "read"
435+
}
436+
},
437+
{
438+
"text": " as *const i8)"
439+
}
440+
],
441+
"params": {
442+
"a0": {
443+
"type": "*const u8",
444+
"is_unsafe_pointer": true
445+
},
446+
"a1": {
447+
"type": "*const u8",
448+
"is_unsafe_pointer": true
449+
}
450+
},
451+
"return_type": {
452+
"type": "i32"
453+
}
454+
},
455+
"f9": {
456+
"body": [
457+
{
458+
"text": "libc::strncmp("
459+
},
460+
{
461+
"placeholder": {
462+
"arg": 0,
463+
"access": "read"
464+
}
465+
},
466+
{
467+
"text": " as *const i8, "
468+
},
469+
{
470+
"placeholder": {
471+
"arg": 1,
472+
"access": "read"
473+
}
474+
},
475+
{
476+
"text": " as *const i8, "
477+
},
478+
{
479+
"placeholder": {
480+
"arg": 2,
481+
"access": "read"
482+
}
483+
},
484+
{
485+
"text": " as usize)"
486+
}
487+
],
488+
"params": {
489+
"a0": {
490+
"type": "*const u8",
491+
"is_unsafe_pointer": true
492+
},
493+
"a1": {
494+
"type": "*const u8",
495+
"is_unsafe_pointer": true
496+
},
497+
"a2": {
498+
"type": "usize"
499+
}
500+
},
501+
"return_type": {
502+
"type": "i32"
503+
}
416504
}
417505
}

rules/cstring/src.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ void *f4(void *dst, const void *src, size_t n) { return memmove(dst, src, n); }
1414
char *f5(const char *a0, int a1) { return strchr(a0, a1); }
1515

1616
size_t f7(const char *a0) { return strlen(a0); }
17+
18+
int f8(const char *a0, const char *a1) { return strcmp(a0, a1); }
19+
20+
int f9(const char *a0, const char *a1, size_t a2) { return strncmp(a0, a1, a2); }

rules/cstring/tgt_unsafe.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,11 @@ unsafe fn f6(a0: *const u8, a1: i32) -> *const u8 {
4747
unsafe fn f7(a0: *const u8) -> u64 {
4848
libc::strlen(a0 as *const i8) as u64
4949
}
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+
}

tests/unit/cstring.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,39 @@ static void test_strlen() {
4949
assert(std::strlen("hello world") == 11);
5050
}
5151

52+
static void test_strcmp() {
53+
assert(std::strcmp("abc", "abc") == 0);
54+
assert(std::strcmp("abc", "abd") < 0);
55+
assert(std::strcmp("abd", "abc") > 0);
56+
const char *p = "abc";
57+
const char *q = "abd";
58+
char buf[] = {'a', 'b', 'c', '\0'};
59+
assert(std::strcmp(p, p) == 0);
60+
assert(std::strcmp(p, q) < 0);
61+
assert(std::strcmp(buf, p) == 0);
62+
}
63+
64+
static void test_strncmp() {
65+
assert(std::strncmp("abcdef", "abcxyz", 3) == 0);
66+
assert(std::strncmp("abcdef", "abcxyz", 4) < 0);
67+
assert(std::strncmp("abcxyz", "abcdef", 4) > 0);
68+
const char *p = "abcdef";
69+
const char *q = "abcxyz";
70+
char buf[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
71+
std::size_t n = 3;
72+
assert(std::strncmp(p, q, n) == 0);
73+
assert(std::strncmp(p, q, n + 1) < 0);
74+
assert(std::strncmp(buf, p, 6) == 0);
75+
}
76+
5277
int main() {
5378
test_memcpy();
5479
test_memset();
5580
test_memcmp();
5681
test_memmove();
5782
test_strchr();
5883
test_strlen();
84+
test_strcmp();
85+
test_strncmp();
5986
return 0;
6087
}

tests/unit/out/unsafe/cstring.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,82 @@ pub unsafe fn test_strlen_5() {
156156
assert!(((libc::strlen(b"hello\0".as_ptr() as *const i8) as u64) == (5_u64)));
157157
assert!(((libc::strlen(b"hello world\0".as_ptr() as *const i8) as u64) == (11_u64)));
158158
}
159+
pub unsafe fn test_strcmp_6() {
160+
assert!(
161+
((libc::strcmp(
162+
b"abc\0".as_ptr() as *const i8,
163+
b"abc\0".as_ptr() as *const i8
164+
)) == (0))
165+
);
166+
assert!(
167+
((libc::strcmp(
168+
b"abc\0".as_ptr() as *const i8,
169+
b"abd\0".as_ptr() as *const i8
170+
)) < (0))
171+
);
172+
assert!(
173+
((libc::strcmp(
174+
b"abd\0".as_ptr() as *const i8,
175+
b"abc\0".as_ptr() as *const i8
176+
)) > (0))
177+
);
178+
let mut p: *const u8 = b"abc\0".as_ptr();
179+
let mut q: *const u8 = b"abd\0".as_ptr();
180+
let mut buf: [u8; 4] = [('a' as u8), ('b' as u8), ('c' as u8), ('\0' as u8)];
181+
assert!(((libc::strcmp(p as *const i8, p as *const i8)) == (0)));
182+
assert!(((libc::strcmp(p as *const i8, q as *const i8)) < (0)));
183+
assert!(((libc::strcmp((buf.as_mut_ptr()).cast_const() as *const i8, p as *const i8)) == (0)));
184+
}
185+
pub unsafe fn test_strncmp_7() {
186+
assert!(
187+
((libc::strncmp(
188+
b"abcdef\0".as_ptr() as *const i8,
189+
b"abcxyz\0".as_ptr() as *const i8,
190+
3_u64 as usize
191+
)) == (0))
192+
);
193+
assert!(
194+
((libc::strncmp(
195+
b"abcdef\0".as_ptr() as *const i8,
196+
b"abcxyz\0".as_ptr() as *const i8,
197+
4_u64 as usize
198+
)) < (0))
199+
);
200+
assert!(
201+
((libc::strncmp(
202+
b"abcxyz\0".as_ptr() as *const i8,
203+
b"abcdef\0".as_ptr() as *const i8,
204+
4_u64 as usize
205+
)) > (0))
206+
);
207+
let mut p: *const u8 = b"abcdef\0".as_ptr();
208+
let mut q: *const u8 = b"abcxyz\0".as_ptr();
209+
let mut buf: [u8; 7] = [
210+
('a' as u8),
211+
('b' as u8),
212+
('c' as u8),
213+
('d' as u8),
214+
('e' as u8),
215+
('f' as u8),
216+
('\0' as u8),
217+
];
218+
let mut n: u64 = 3_u64;
219+
assert!(((libc::strncmp(p as *const i8, q as *const i8, n as usize)) == (0)));
220+
assert!(
221+
((libc::strncmp(
222+
p as *const i8,
223+
q as *const i8,
224+
(n).wrapping_add(1_u64) as usize
225+
)) < (0))
226+
);
227+
assert!(
228+
((libc::strncmp(
229+
(buf.as_mut_ptr()).cast_const() as *const i8,
230+
p as *const i8,
231+
6_u64 as usize
232+
)) == (0))
233+
);
234+
}
159235
pub fn main() {
160236
unsafe {
161237
std::process::exit(main_0() as i32);
@@ -168,5 +244,7 @@ unsafe fn main_0() -> i32 {
168244
(unsafe { test_memmove_3() });
169245
(unsafe { test_strchr_4() });
170246
(unsafe { test_strlen_5() });
247+
(unsafe { test_strcmp_6() });
248+
(unsafe { test_strncmp_7() });
171249
return 0;
172250
}

tests/unit/out/unsafe/string_h.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,99 @@ pub unsafe fn test_strlen_5() {
192192
!= 0)
193193
);
194194
}
195+
pub unsafe fn test_strcmp_6() {
196+
assert!(
197+
((((libc::strcmp(
198+
(b"abc\0".as_ptr().cast_mut()).cast_const() as *const i8,
199+
(b"abc\0".as_ptr().cast_mut()).cast_const() as *const i8
200+
)) == (0)) as i32)
201+
!= 0)
202+
);
203+
assert!(
204+
((((libc::strcmp(
205+
(b"abc\0".as_ptr().cast_mut()).cast_const() as *const i8,
206+
(b"abd\0".as_ptr().cast_mut()).cast_const() as *const i8
207+
)) < (0)) as i32)
208+
!= 0)
209+
);
210+
assert!(
211+
((((libc::strcmp(
212+
(b"abd\0".as_ptr().cast_mut()).cast_const() as *const i8,
213+
(b"abc\0".as_ptr().cast_mut()).cast_const() as *const i8
214+
)) > (0)) as i32)
215+
!= 0)
216+
);
217+
let mut p: *const u8 = (b"abc\0".as_ptr().cast_mut()).cast_const();
218+
let mut q: *const u8 = (b"abd\0".as_ptr().cast_mut()).cast_const();
219+
let mut buf: [u8; 4] = [
220+
(('a' as i32) as u8),
221+
(('b' as i32) as u8),
222+
(('c' as i32) as u8),
223+
(('\0' as i32) as u8),
224+
];
225+
assert!(((((libc::strcmp(p as *const i8, p as *const i8)) == (0)) as i32) != 0));
226+
assert!(((((libc::strcmp(p as *const i8, q as *const i8)) < (0)) as i32) != 0));
227+
assert!(
228+
((((libc::strcmp((buf.as_mut_ptr()).cast_const() as *const i8, p as *const i8)) == (0))
229+
as i32)
230+
!= 0)
231+
);
232+
}
233+
pub unsafe fn test_strncmp_7() {
234+
assert!(
235+
((((libc::strncmp(
236+
(b"abcdef\0".as_ptr().cast_mut()).cast_const() as *const i8,
237+
(b"abcxyz\0".as_ptr().cast_mut()).cast_const() as *const i8,
238+
3_u64 as usize
239+
)) == (0)) as i32)
240+
!= 0)
241+
);
242+
assert!(
243+
((((libc::strncmp(
244+
(b"abcdef\0".as_ptr().cast_mut()).cast_const() as *const i8,
245+
(b"abcxyz\0".as_ptr().cast_mut()).cast_const() as *const i8,
246+
4_u64 as usize
247+
)) < (0)) as i32)
248+
!= 0)
249+
);
250+
assert!(
251+
((((libc::strncmp(
252+
(b"abcxyz\0".as_ptr().cast_mut()).cast_const() as *const i8,
253+
(b"abcdef\0".as_ptr().cast_mut()).cast_const() as *const i8,
254+
4_u64 as usize
255+
)) > (0)) as i32)
256+
!= 0)
257+
);
258+
let mut p: *const u8 = (b"abcdef\0".as_ptr().cast_mut()).cast_const();
259+
let mut q: *const u8 = (b"abcxyz\0".as_ptr().cast_mut()).cast_const();
260+
let mut buf: [u8; 7] = [
261+
(('a' as i32) as u8),
262+
(('b' as i32) as u8),
263+
(('c' as i32) as u8),
264+
(('d' as i32) as u8),
265+
(('e' as i32) as u8),
266+
(('f' as i32) as u8),
267+
(('\0' as i32) as u8),
268+
];
269+
let mut n: u64 = 3_u64;
270+
assert!(((((libc::strncmp(p as *const i8, q as *const i8, n as usize)) == (0)) as i32) != 0));
271+
assert!(
272+
((((libc::strncmp(
273+
p as *const i8,
274+
q as *const i8,
275+
(n).wrapping_add(1_u64) as usize
276+
)) < (0)) as i32)
277+
!= 0)
278+
);
279+
assert!(
280+
((((libc::strncmp(
281+
(buf.as_mut_ptr()).cast_const() as *const i8,
282+
p as *const i8,
283+
6_u64 as usize
284+
)) == (0)) as i32)
285+
!= 0)
286+
);
287+
}
195288
pub fn main() {
196289
unsafe {
197290
std::process::exit(main_0() as i32);
@@ -204,5 +297,7 @@ unsafe fn main_0() -> i32 {
204297
(unsafe { test_memmove_3() });
205298
(unsafe { test_strchr_4() });
206299
(unsafe { test_strlen_5() });
300+
(unsafe { test_strcmp_6() });
301+
(unsafe { test_strncmp_7() });
207302
return 0;
208303
}

tests/unit/string_h.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,39 @@ static void test_strlen(void) {
4949
assert(strlen("hello world") == 11);
5050
}
5151

52+
static void test_strcmp(void) {
53+
assert(strcmp("abc", "abc") == 0);
54+
assert(strcmp("abc", "abd") < 0);
55+
assert(strcmp("abd", "abc") > 0);
56+
const char *p = "abc";
57+
const char *q = "abd";
58+
char buf[] = {'a', 'b', 'c', '\0'};
59+
assert(strcmp(p, p) == 0);
60+
assert(strcmp(p, q) < 0);
61+
assert(strcmp(buf, p) == 0);
62+
}
63+
64+
static void test_strncmp(void) {
65+
assert(strncmp("abcdef", "abcxyz", 3) == 0);
66+
assert(strncmp("abcdef", "abcxyz", 4) < 0);
67+
assert(strncmp("abcxyz", "abcdef", 4) > 0);
68+
const char *p = "abcdef";
69+
const char *q = "abcxyz";
70+
char buf[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
71+
size_t n = 3;
72+
assert(strncmp(p, q, n) == 0);
73+
assert(strncmp(p, q, n + 1) < 0);
74+
assert(strncmp(buf, p, 6) == 0);
75+
}
76+
5277
int main(void) {
5378
test_memcpy();
5479
test_memset();
5580
test_memcmp();
5681
test_memmove();
5782
test_strchr();
5883
test_strlen();
84+
test_strcmp();
85+
test_strncmp();
5986
return 0;
6087
}

0 commit comments

Comments
 (0)