/src/ntp-dev/lib/isc/tsmemcmp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") |
3 | | * Copyright (C) 1999-2001, 2003 Internet Software Consortium. |
4 | | * |
5 | | * Permission to use, copy, modify, and/or distribute this software for any |
6 | | * purpose with or without fee is hereby granted, provided that the above |
7 | | * copyright notice and this permission notice appear in all copies. |
8 | | * |
9 | | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH |
10 | | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
11 | | * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, |
12 | | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
13 | | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
14 | | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
15 | | * PERFORMANCE OF THIS SOFTWARE. |
16 | | */ |
17 | | |
18 | | /* $Id$ */ |
19 | | |
20 | | /*! \file */ |
21 | | |
22 | | #include <config.h> |
23 | | #include <limits.h> |
24 | | #include <isc/string.h> |
25 | | |
26 | | /* Making a portable memcmp that has no internal branches and loops always |
27 | | * once for every byte without early-out shortcut has a few challenges. |
28 | | * |
29 | | * Inspired by 'timingsafe_memcmp()' from the BSD system and |
30 | | * https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/string/timingsafe_memcmp.c |
31 | | * |
32 | | * Sadly, that one is not portable C: It makes assumptions on the representation |
33 | | * of negative integers and assumes sign-preserving right-shift of negative |
34 | | * signed values. This is a rewrite from scratch that should not suffer from |
35 | | * such issues. |
36 | | * |
37 | | * 2015-12-12, J. Perlinger (perlinger-at-ntp-dot-org) |
38 | | */ |
39 | | int |
40 | 0 | isc_tsmemcmp(const void *p1, const void *p2, size_t nb) { |
41 | 0 | const unsigned char *ucp1 = p1; |
42 | 0 | const unsigned char *ucp2 = p2; |
43 | 0 | unsigned int isLT = 0u; |
44 | 0 | unsigned int isGT = 0u; |
45 | 0 | volatile unsigned int mask = (1u << CHAR_BIT); |
46 | |
|
47 | 0 | for (/*NOP*/; 0 != nb; --nb, ++ucp1, ++ucp2) { |
48 | 0 | isLT |= mask & |
49 | 0 | ((unsigned int)*ucp1 - (unsigned int)*ucp2); |
50 | 0 | isGT |= mask & |
51 | 0 | ((unsigned int)*ucp2 - (unsigned int)*ucp1); |
52 | 0 | mask &= ~(isLT | isGT); |
53 | 0 | } |
54 | 0 | return (int)(isGT >> CHAR_BIT) - (int)(isLT >> CHAR_BIT); |
55 | 0 | } |