1950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris/*
2950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * Copyright (C) 2014 The Android Open Source Project
3950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * All rights reserved.
4950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *
5950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * Redistribution and use in source and binary forms, with or without
6950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * modification, are permitted provided that the following conditions
7950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * are met:
8950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *  * Redistributions of source code must retain the above copyright
9950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *    notice, this list of conditions and the following disclaimer.
10950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *  * Redistributions in binary form must reproduce the above copyright
11950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *    notice, this list of conditions and the following disclaimer in
12950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *    the documentation and/or other materials provided with the
13950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *    distribution.
14950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *
15950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * SUCH DAMAGE.
27950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris */
28950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris
29950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris#undef _FORTIFY_SOURCE
30950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris
31950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris#include <string.h>
32950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris#include <stdlib.h>
33950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris#include "private/libc_logging.h"
34950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris
35950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris/*
36950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * Runtime implementation of __builtin____stpncpy_chk.
37950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *
38950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * See
39950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
40950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
41950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * for details.
42950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *
43950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * This stpncpy check is called if _FORTIFY_SOURCE is defined and
44950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * greater than 0.
45950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris */
46950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferrisextern "C" char* __stpncpy_chk(char* __restrict dest, const char* __restrict src,
47950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris                               size_t len, size_t dest_len) {
48950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris  if (__predict_false(len > dest_len)) {
49950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    __fortify_chk_fail("stpncpy: prevented write past end of buffer",
50950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris                       BIONIC_EVENT_STPNCPY_BUFFER_OVERFLOW);
51950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris  }
52950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris
53950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris  return stpncpy(dest, src, len);
54950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris}
55950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris
56950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris/*
57950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * __stpncpy_chk2
58950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris *
59950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * This is a variant of __stpncpy_chk, but it also checks to make
60950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * sure we don't read beyond the end of "src". The code for this is
61950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * based on the original version of stpncpy, but modified to check
62950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris * how much we read from "src" at the end of the copy operation.
63950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris */
64950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferrisextern "C" char* __stpncpy_chk2(char* __restrict dst, const char* __restrict src,
65950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris              size_t n, size_t dest_len, size_t src_len)
66950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris{
67950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris  if (__predict_false(n > dest_len)) {
68950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    __fortify_chk_fail("stpncpy: prevented write past end of buffer",
69950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris                       BIONIC_EVENT_STPNCPY_BUFFER_OVERFLOW);
70950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris  }
71950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris  if (n != 0) {
72950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    char* d = dst;
73950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    const char* s = src;
74950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris
75950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    do {
76950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris      if ((*d++ = *s++) == 0) {
77950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris        /* NUL pad the remaining n-1 bytes */
78950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris        while (--n != 0) {
79950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris          *d++ = 0;
80950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris        }
81950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris        break;
82950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris      }
83950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    } while (--n != 0);
84950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris
85950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    size_t s_copy_len = static_cast<size_t>(s - src);
86950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    if (__predict_false(s_copy_len > src_len)) {
87950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris      __fortify_chk_fail("stpncpy: prevented read past end of buffer", 0);
88950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris    }
89950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris  }
90950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris
91950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris  return dst;
92950a58e24d1019eb9d814dbb16f111a6b61e3f23Christopher Ferris}
93