LCOV - code coverage report
Current view: top level - basic - escape.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 288 312 92.3 %
Date: 2019-08-23 13:36:53 Functions: 13 13 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 170 209 81.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <stdlib.h>
       5                 :            : #include <string.h>
       6                 :            : 
       7                 :            : #include "alloc-util.h"
       8                 :            : #include "escape.h"
       9                 :            : #include "hexdecoct.h"
      10                 :            : #include "macro.h"
      11                 :            : #include "utf8.h"
      12                 :            : 
      13                 :   12666428 : int cescape_char(char c, char *buf) {
      14                 :   12666428 :         char *buf_old = buf;
      15                 :            : 
      16                 :            :         /* Needs space for 4 characters in the buffer */
      17                 :            : 
      18   [ +  +  +  +  :   12666428 :         switch (c) {
          +  +  +  +  +  
                   +  + ]
      19                 :            : 
      20                 :         28 :                 case '\a':
      21                 :         28 :                         *(buf++) = '\\';
      22                 :         28 :                         *(buf++) = 'a';
      23                 :         28 :                         break;
      24                 :         36 :                 case '\b':
      25                 :         36 :                         *(buf++) = '\\';
      26                 :         36 :                         *(buf++) = 'b';
      27                 :         36 :                         break;
      28                 :         28 :                 case '\f':
      29                 :         28 :                         *(buf++) = '\\';
      30                 :         28 :                         *(buf++) = 'f';
      31                 :         28 :                         break;
      32                 :        416 :                 case '\n':
      33                 :        416 :                         *(buf++) = '\\';
      34                 :        416 :                         *(buf++) = 'n';
      35                 :        416 :                         break;
      36                 :         12 :                 case '\r':
      37                 :         12 :                         *(buf++) = '\\';
      38                 :         12 :                         *(buf++) = 'r';
      39                 :         12 :                         break;
      40                 :        104 :                 case '\t':
      41                 :        104 :                         *(buf++) = '\\';
      42                 :        104 :                         *(buf++) = 't';
      43                 :        104 :                         break;
      44                 :          8 :                 case '\v':
      45                 :          8 :                         *(buf++) = '\\';
      46                 :          8 :                         *(buf++) = 'v';
      47                 :          8 :                         break;
      48                 :         60 :                 case '\\':
      49                 :         60 :                         *(buf++) = '\\';
      50                 :         60 :                         *(buf++) = '\\';
      51                 :         60 :                         break;
      52                 :        240 :                 case '"':
      53                 :        240 :                         *(buf++) = '\\';
      54                 :        240 :                         *(buf++) = '"';
      55                 :        240 :                         break;
      56                 :        156 :                 case '\'':
      57                 :        156 :                         *(buf++) = '\\';
      58                 :        156 :                         *(buf++) = '\'';
      59                 :        156 :                         break;
      60                 :            : 
      61                 :   12665340 :                 default:
      62                 :            :                         /* For special chars we prefer octal over
      63                 :            :                          * hexadecimal encoding, simply because glib's
      64                 :            :                          * g_strescape() does the same */
      65   [ +  +  +  + ]:   12665340 :                         if ((c < ' ') || (c >= 127)) {
      66                 :      39408 :                                 *(buf++) = '\\';
      67                 :      39408 :                                 *(buf++) = octchar((unsigned char) c >> 6);
      68                 :      39408 :                                 *(buf++) = octchar((unsigned char) c >> 3);
      69                 :      39408 :                                 *(buf++) = octchar((unsigned char) c);
      70                 :            :                         } else
      71                 :   12625932 :                                 *(buf++) = c;
      72                 :   12665340 :                         break;
      73                 :            :         }
      74                 :            : 
      75                 :   12666428 :         return buf - buf_old;
      76                 :            : }
      77                 :            : 
      78                 :        308 : char *cescape_length(const char *s, size_t n) {
      79                 :            :         const char *f;
      80                 :            :         char *r, *t;
      81                 :            : 
      82   [ -  +  #  # ]:        308 :         assert(s || n == 0);
      83                 :            : 
      84                 :            :         /* Does C style string escaping. May be reversed with
      85                 :            :          * cunescape(). */
      86                 :            : 
      87                 :        308 :         r = new(char, n*4 + 1);
      88         [ -  + ]:        308 :         if (!r)
      89                 :          0 :                 return NULL;
      90                 :            : 
      91         [ +  + ]:   12590628 :         for (f = s, t = r; f < s + n; f++)
      92                 :   12590320 :                 t += cescape_char(*f, t);
      93                 :            : 
      94                 :        308 :         *t = 0;
      95                 :            : 
      96                 :        308 :         return r;
      97                 :            : }
      98                 :            : 
      99                 :        160 : char *cescape(const char *s) {
     100         [ -  + ]:        160 :         assert(s);
     101                 :            : 
     102                 :        160 :         return cescape_length(s, strlen(s));
     103                 :            : }
     104                 :            : 
     105                 :        484 : int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) {
     106                 :        484 :         int r = 1;
     107                 :            : 
     108         [ -  + ]:        484 :         assert(p);
     109         [ -  + ]:        484 :         assert(ret);
     110                 :            : 
     111                 :            :         /* Unescapes C style. Returns the unescaped character in ret.
     112                 :            :          * Sets *eight_bit to true if the escaped sequence either fits in
     113                 :            :          * one byte in UTF-8 or is a non-unicode literal byte and should
     114                 :            :          * instead be copied directly.
     115                 :            :          */
     116                 :            : 
     117   [ +  +  -  + ]:        484 :         if (length != (size_t) -1 && length < 1)
     118                 :          0 :                 return -EINVAL;
     119                 :            : 
     120   [ +  +  +  +  :        484 :         switch (p[0]) {
          +  +  +  +  +  
          +  +  +  +  +  
                   +  + ]
     121                 :            : 
     122                 :         12 :         case 'a':
     123                 :         12 :                 *ret = '\a';
     124                 :         12 :                 break;
     125                 :         28 :         case 'b':
     126                 :         28 :                 *ret = '\b';
     127                 :         28 :                 break;
     128                 :         12 :         case 'f':
     129                 :         12 :                 *ret = '\f';
     130                 :         12 :                 break;
     131                 :         40 :         case 'n':
     132                 :         40 :                 *ret = '\n';
     133                 :         40 :                 break;
     134                 :         12 :         case 'r':
     135                 :         12 :                 *ret = '\r';
     136                 :         12 :                 break;
     137                 :         20 :         case 't':
     138                 :         20 :                 *ret = '\t';
     139                 :         20 :                 break;
     140                 :         12 :         case 'v':
     141                 :         12 :                 *ret = '\v';
     142                 :         12 :                 break;
     143                 :         24 :         case '\\':
     144                 :         24 :                 *ret = '\\';
     145                 :         24 :                 break;
     146                 :         28 :         case '"':
     147                 :         28 :                 *ret = '"';
     148                 :         28 :                 break;
     149                 :          8 :         case '\'':
     150                 :          8 :                 *ret = '\'';
     151                 :          8 :                 break;
     152                 :            : 
     153                 :         12 :         case 's':
     154                 :            :                 /* This is an extension of the XDG syntax files */
     155                 :         12 :                 *ret = ' ';
     156                 :         12 :                 break;
     157                 :            : 
     158                 :         44 :         case 'x': {
     159                 :            :                 /* hexadecimal encoding */
     160                 :            :                 int a, b;
     161                 :            : 
     162   [ +  +  +  + ]:         44 :                 if (length != (size_t) -1 && length < 3)
     163                 :         16 :                         return -EINVAL;
     164                 :            : 
     165                 :         28 :                 a = unhexchar(p[1]);
     166         [ +  + ]:         28 :                 if (a < 0)
     167                 :          8 :                         return -EINVAL;
     168                 :            : 
     169                 :         20 :                 b = unhexchar(p[2]);
     170         [ -  + ]:         20 :                 if (b < 0)
     171                 :          0 :                         return -EINVAL;
     172                 :            : 
     173                 :            :                 /* Don't allow NUL bytes */
     174   [ +  +  +  - ]:         20 :                 if (a == 0 && b == 0)
     175                 :          4 :                         return -EINVAL;
     176                 :            : 
     177                 :         16 :                 *ret = (a << 4U) | b;
     178                 :         16 :                 *eight_bit = true;
     179                 :         16 :                 r = 3;
     180                 :         16 :                 break;
     181                 :            :         }
     182                 :            : 
     183                 :         20 :         case 'u': {
     184                 :            :                 /* C++11 style 16bit unicode */
     185                 :            : 
     186                 :            :                 int a[4];
     187                 :            :                 size_t i;
     188                 :            :                 uint32_t c;
     189                 :            : 
     190   [ +  +  -  + ]:         20 :                 if (length != (size_t) -1 && length < 5)
     191                 :          4 :                         return -EINVAL;
     192                 :            : 
     193         [ +  + ]:        100 :                 for (i = 0; i < 4; i++) {
     194                 :         80 :                         a[i] = unhexchar(p[1 + i]);
     195         [ -  + ]:         80 :                         if (a[i] < 0)
     196                 :          0 :                                 return a[i];
     197                 :            :                 }
     198                 :            : 
     199                 :         20 :                 c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
     200                 :            : 
     201                 :            :                 /* Don't allow 0 chars */
     202         [ +  + ]:         20 :                 if (c == 0)
     203                 :          4 :                         return -EINVAL;
     204                 :            : 
     205                 :         16 :                 *ret = c;
     206                 :         16 :                 r = 5;
     207                 :         16 :                 break;
     208                 :            :         }
     209                 :            : 
     210                 :         16 :         case 'U': {
     211                 :            :                 /* C++11 style 32bit unicode */
     212                 :            : 
     213                 :            :                 int a[8];
     214                 :            :                 size_t i;
     215                 :            :                 char32_t c;
     216                 :            : 
     217   [ +  +  -  + ]:         16 :                 if (length != (size_t) -1 && length < 9)
     218                 :          0 :                         return -EINVAL;
     219                 :            : 
     220         [ +  + ]:        144 :                 for (i = 0; i < 8; i++) {
     221                 :        128 :                         a[i] = unhexchar(p[1 + i]);
     222         [ -  + ]:        128 :                         if (a[i] < 0)
     223                 :          0 :                                 return a[i];
     224                 :            :                 }
     225                 :            : 
     226                 :         48 :                 c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
     227                 :         32 :                     ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] <<  8U) | ((uint32_t) a[6] <<  4U) |  (uint32_t) a[7];
     228                 :            : 
     229                 :            :                 /* Don't allow 0 chars */
     230         [ -  + ]:         16 :                 if (c == 0)
     231                 :          0 :                         return -EINVAL;
     232                 :            : 
     233                 :            :                 /* Don't allow invalid code points */
     234         [ -  + ]:         16 :                 if (!unichar_is_valid(c))
     235                 :          0 :                         return -EINVAL;
     236                 :            : 
     237                 :         16 :                 *ret = c;
     238                 :         16 :                 r = 9;
     239                 :         16 :                 break;
     240                 :            :         }
     241                 :            : 
     242                 :        112 :         case '0':
     243                 :            :         case '1':
     244                 :            :         case '2':
     245                 :            :         case '3':
     246                 :            :         case '4':
     247                 :            :         case '5':
     248                 :            :         case '6':
     249                 :            :         case '7': {
     250                 :            :                 /* octal encoding */
     251                 :            :                 int a, b, c;
     252                 :            :                 char32_t m;
     253                 :            : 
     254   [ +  +  +  + ]:        112 :                 if (length != (size_t) -1 && length < 3)
     255                 :         16 :                         return -EINVAL;
     256                 :            : 
     257                 :         96 :                 a = unoctchar(p[0]);
     258         [ -  + ]:         96 :                 if (a < 0)
     259                 :          0 :                         return -EINVAL;
     260                 :            : 
     261                 :         96 :                 b = unoctchar(p[1]);
     262         [ -  + ]:         96 :                 if (b < 0)
     263                 :          0 :                         return -EINVAL;
     264                 :            : 
     265                 :         96 :                 c = unoctchar(p[2]);
     266         [ -  + ]:         96 :                 if (c < 0)
     267                 :          0 :                         return -EINVAL;
     268                 :            : 
     269                 :            :                 /* don't allow NUL bytes */
     270   [ +  +  +  +  :         96 :                 if (a == 0 && b == 0 && c == 0)
                   +  + ]
     271                 :          8 :                         return -EINVAL;
     272                 :            : 
     273                 :            :                 /* Don't allow bytes above 255 */
     274                 :         88 :                 m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
     275         [ -  + ]:         88 :                 if (m > 255)
     276                 :          0 :                         return -EINVAL;
     277                 :            : 
     278                 :         88 :                 *ret = m;
     279                 :         88 :                 *eight_bit = true;
     280                 :         88 :                 r = 3;
     281                 :         88 :                 break;
     282                 :            :         }
     283                 :            : 
     284                 :         84 :         default:
     285                 :         84 :                 return -EINVAL;
     286                 :            :         }
     287                 :            : 
     288                 :        344 :         return r;
     289                 :            : }
     290                 :            : 
     291                 :        372 : int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
     292                 :            :         char *r, *t;
     293                 :            :         const char *f;
     294                 :            :         size_t pl;
     295                 :            : 
     296         [ -  + ]:        372 :         assert(s);
     297         [ -  + ]:        372 :         assert(ret);
     298                 :            : 
     299                 :            :         /* Undoes C style string escaping, and optionally prefixes it. */
     300                 :            : 
     301                 :        372 :         pl = strlen_ptr(prefix);
     302                 :            : 
     303                 :        372 :         r = new(char, pl+length+1);
     304         [ -  + ]:        372 :         if (!r)
     305                 :          0 :                 return -ENOMEM;
     306                 :            : 
     307         [ -  + ]:        372 :         if (prefix)
     308                 :          0 :                 memcpy(r, prefix, pl);
     309                 :            : 
     310         [ +  + ]:       2928 :         for (f = s, t = r + pl; f < s + length; f++) {
     311                 :            :                 size_t remaining;
     312                 :       2592 :                 bool eight_bit = false;
     313                 :            :                 char32_t u;
     314                 :            :                 int k;
     315                 :            : 
     316                 :       2592 :                 remaining = s + length - f;
     317         [ -  + ]:       2592 :                 assert(remaining > 0);
     318                 :            : 
     319         [ +  + ]:       2592 :                 if (*f != '\\') {
     320                 :            :                         /* A literal, copy verbatim */
     321                 :       2288 :                         *(t++) = *f;
     322                 :       2316 :                         continue;
     323                 :            :                 }
     324                 :            : 
     325         [ +  + ]:        304 :                 if (remaining == 1) {
     326         [ +  + ]:         12 :                         if (flags & UNESCAPE_RELAX) {
     327                 :            :                                 /* A trailing backslash, copy verbatim */
     328                 :          4 :                                 *(t++) = *f;
     329                 :          4 :                                 continue;
     330                 :            :                         }
     331                 :            : 
     332                 :          8 :                         free(r);
     333                 :         36 :                         return -EINVAL;
     334                 :            :                 }
     335                 :            : 
     336                 :        292 :                 k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
     337         [ +  + ]:        292 :                 if (k < 0) {
     338         [ +  + ]:         52 :                         if (flags & UNESCAPE_RELAX) {
     339                 :            :                                 /* Invalid escape code, let's take it literal then */
     340                 :         24 :                                 *(t++) = '\\';
     341                 :         24 :                                 continue;
     342                 :            :                         }
     343                 :            : 
     344                 :         28 :                         free(r);
     345                 :         28 :                         return k;
     346                 :            :                 }
     347                 :            : 
     348                 :        240 :                 f += k;
     349         [ +  + ]:        240 :                 if (eight_bit)
     350                 :            :                         /* One byte? Set directly as specified */
     351                 :         84 :                         *(t++) = u;
     352                 :            :                 else
     353                 :            :                         /* Otherwise encode as multi-byte UTF-8 */
     354                 :        156 :                         t += utf8_encode_unichar(t, u);
     355                 :            :         }
     356                 :            : 
     357                 :        336 :         *t = 0;
     358                 :            : 
     359                 :        336 :         *ret = r;
     360                 :        336 :         return t - r;
     361                 :            : }
     362                 :            : 
     363                 :        372 : int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
     364                 :        372 :         return cunescape_length_with_prefix(s, length, NULL, flags, ret);
     365                 :            : }
     366                 :            : 
     367                 :        372 : int cunescape(const char *s, UnescapeFlags flags, char **ret) {
     368                 :        372 :         return cunescape_length(s, strlen(s), flags, ret);
     369                 :            : }
     370                 :            : 
     371                 :        484 : char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) {
     372                 :            :         char *ans, *t, *prev, *prev2;
     373                 :            :         const char *f;
     374                 :            : 
     375                 :            :         /* Escapes all chars in bad, in addition to \ and all special chars, in \xFF style escaping. May be
     376                 :            :          * reversed with cunescape(). If eight_bits is true, characters >= 127 are let through unchanged.
     377                 :            :          * This corresponds to non-ASCII printable characters in pre-unicode encodings.
     378                 :            :          *
     379                 :            :          * If console_width is reached, output is truncated and "..." is appended. */
     380                 :            : 
     381         [ +  + ]:        484 :         if (console_width == 0)
     382                 :          8 :                 return strdup("");
     383                 :            : 
     384                 :        476 :         ans = new(char, MIN(strlen(s), console_width) * 4 + 1);
     385         [ -  + ]:        476 :         if (!ans)
     386                 :          0 :                 return NULL;
     387                 :            : 
     388                 :        476 :         memset(ans, '_', MIN(strlen(s), console_width) * 4);
     389                 :        476 :         ans[MIN(strlen(s), console_width) * 4] = 0;
     390                 :            : 
     391                 :        476 :         for (f = s, t = prev = prev2 = ans; ; f++) {
     392                 :       4948 :                 char *tmp_t = t;
     393                 :            : 
     394         [ +  + ]:       4948 :                 if (!*f) {
     395                 :         80 :                         *t = 0;
     396                 :         80 :                         return ans;
     397                 :            :                 }
     398                 :            : 
     399   [ +  +  +  +  :       4868 :                 if ((unsigned char) *f < ' ' || (!eight_bits && (unsigned char) *f >= 127) ||
                   +  + ]
     400   [ +  +  +  + ]:       2428 :                     *f == '\\' || strchr(bad, *f)) {
     401         [ +  + ]:       3348 :                         if ((size_t) (t - ans) + 4 > console_width)
     402                 :        368 :                                 break;
     403                 :            : 
     404                 :       2980 :                         *(t++) = '\\';
     405                 :       2980 :                         *(t++) = 'x';
     406                 :       2980 :                         *(t++) = hexchar(*f >> 4);
     407                 :       2980 :                         *(t++) = hexchar(*f);
     408                 :            :                 } else {
     409         [ +  + ]:       1520 :                         if ((size_t) (t - ans) + 1 > console_width)
     410                 :         28 :                                 break;
     411                 :            : 
     412                 :       1492 :                         *(t++) = *f;
     413                 :            :                 }
     414                 :            : 
     415                 :            :                 /* We might need to go back two cycles to fit three dots, so remember two positions */
     416                 :       4472 :                 prev2 = prev;
     417                 :       4472 :                 prev = tmp_t;
     418                 :            :         }
     419                 :            : 
     420                 :            :         /* We can just write where we want, since chars are one-byte */
     421                 :        396 :         size_t c = MIN(console_width, 3u); /* If the console is too narrow, write fewer dots */
     422                 :            :         size_t off;
     423         [ +  + ]:        396 :         if (console_width - c >= (size_t) (t - ans))
     424                 :         92 :                 off = (size_t) (t - ans);
     425         [ +  + ]:        304 :         else if (console_width - c >= (size_t) (prev - ans))
     426                 :        264 :                 off = (size_t) (prev - ans);
     427         [ +  + ]:         40 :         else if (console_width - c >= (size_t) (prev2 - ans))
     428                 :         36 :                 off = (size_t) (prev2 - ans);
     429                 :            :         else
     430                 :          4 :                 off = console_width - c;
     431         [ -  + ]:        396 :         assert(off <= (size_t) (t - ans));
     432                 :            : 
     433                 :        396 :         memcpy(ans + off, "...", c);
     434                 :        396 :         ans[off + c] = '\0';
     435                 :        396 :         return ans;
     436                 :            : }
     437                 :            : 
     438                 :         40 : char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) {
     439         [ -  + ]:         40 :         if (eight_bit)
     440                 :          0 :                 return xescape_full(str, "", console_width, true);
     441                 :            :         else
     442                 :         40 :                 return utf8_escape_non_printable_full(str, console_width);
     443                 :            : }
     444                 :            : 
     445                 :        120 : char *octescape(const char *s, size_t len) {
     446                 :            :         char *r, *t;
     447                 :            :         const char *f;
     448                 :            : 
     449                 :            :         /* Escapes all chars in bad, in addition to \ and " chars,
     450                 :            :          * in \nnn style escaping. */
     451                 :            : 
     452                 :        120 :         r = new(char, len * 4 + 1);
     453         [ -  + ]:        120 :         if (!r)
     454                 :          0 :                 return NULL;
     455                 :            : 
     456         [ +  + ]:       1560 :         for (f = s, t = r; f < s + len; f++) {
     457                 :            : 
     458   [ +  -  +  -  :       1440 :                 if (*f < ' ' || *f >= 127 || IN_SET(*f, '\\', '"')) {
             -  +  -  + ]
     459                 :          0 :                         *(t++) = '\\';
     460                 :          0 :                         *(t++) = '0' + (*f >> 6);
     461                 :          0 :                         *(t++) = '0' + ((*f >> 3) & 8);
     462                 :          0 :                         *(t++) = '0' + (*f & 8);
     463                 :            :                 } else
     464                 :       1440 :                         *(t++) = *f;
     465                 :            :         }
     466                 :            : 
     467                 :        120 :         *t = 0;
     468                 :            : 
     469                 :        120 :         return r;
     470                 :            : 
     471                 :            : }
     472                 :            : 
     473                 :        104 : static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) {
     474         [ -  + ]:        104 :         assert(bad);
     475                 :            : 
     476         [ +  + ]:        576 :         for (; *s; s++) {
     477   [ +  +  +  +  :        472 :                 if (escape_tab_nl && IN_SET(*s, '\n', '\t')) {
                   +  + ]
     478                 :         12 :                         *(t++) = '\\';
     479         [ +  + ]:         12 :                         *(t++) = *s == '\n' ? 'n' : 't';
     480                 :         12 :                         continue;
     481                 :            :                 }
     482                 :            : 
     483   [ +  +  +  + ]:        460 :                 if (*s == '\\' || strchr(bad, *s))
     484                 :         56 :                         *(t++) = '\\';
     485                 :            : 
     486                 :        460 :                 *(t++) = *s;
     487                 :            :         }
     488                 :            : 
     489                 :        104 :         return t;
     490                 :            : }
     491                 :            : 
     492                 :         32 : char *shell_escape(const char *s, const char *bad) {
     493                 :            :         char *r, *t;
     494                 :            : 
     495                 :         32 :         r = new(char, strlen(s)*2+1);
     496         [ -  + ]:         32 :         if (!r)
     497                 :          0 :                 return NULL;
     498                 :            : 
     499                 :         32 :         t = strcpy_backslash_escaped(r, s, bad, false);
     500                 :         32 :         *t = 0;
     501                 :            : 
     502                 :         32 :         return r;
     503                 :            : }
     504                 :            : 
     505                 :         88 : char* shell_maybe_quote(const char *s, EscapeStyle style) {
     506                 :            :         const char *p;
     507                 :            :         char *r, *t;
     508                 :            : 
     509         [ -  + ]:         88 :         assert(s);
     510                 :            : 
     511                 :            :         /* Encloses a string in quotes if necessary to make it OK as a shell
     512                 :            :          * string. Note that we treat benign UTF-8 characters as needing
     513                 :            :          * escaping too, but that should be OK. */
     514                 :            : 
     515         [ +  + ]:        288 :         for (p = s; *p; p++)
     516         [ +  + ]:        272 :                 if (*p <= ' ' ||
     517         [ +  - ]:        232 :                     *p >= 127 ||
     518         [ +  + ]:        232 :                     strchr(SHELL_NEED_QUOTES, *p))
     519                 :            :                         break;
     520                 :            : 
     521         [ +  + ]:         88 :         if (!*p)
     522                 :         16 :                 return strdup(s);
     523                 :            : 
     524         [ +  + ]:         72 :         r = new(char, (style == ESCAPE_POSIX) + 1 + strlen(s)*2 + 1 + 1);
     525         [ -  + ]:         72 :         if (!r)
     526                 :          0 :                 return NULL;
     527                 :            : 
     528                 :         72 :         t = r;
     529         [ +  + ]:         72 :         if (style == ESCAPE_BACKSLASH)
     530                 :         36 :                 *(t++) = '"';
     531         [ +  - ]:         36 :         else if (style == ESCAPE_POSIX) {
     532                 :         36 :                 *(t++) = '$';
     533                 :         36 :                 *(t++) = '\'';
     534                 :            :         } else
     535                 :          0 :                 assert_not_reached("Bad EscapeStyle");
     536                 :            : 
     537                 :         72 :         t = mempcpy(t, s, p - s);
     538                 :            : 
     539         [ +  + ]:         72 :         if (style == ESCAPE_BACKSLASH)
     540                 :         36 :                 t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE, false);
     541                 :            :         else
     542                 :         36 :                 t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true);
     543                 :            : 
     544         [ +  + ]:         72 :         if (style == ESCAPE_BACKSLASH)
     545                 :         36 :                 *(t++) = '"';
     546                 :            :         else
     547                 :         36 :                 *(t++) = '\'';
     548                 :         72 :         *t = 0;
     549                 :            : 
     550                 :         72 :         return r;
     551                 :            : }

Generated by: LCOV version 1.14