mc/mhl/escape.h
Patrick Winnertz c83e1995e4 Merge branch '241_buffer_overflow' into mc-4.6
* 241_buffer_overflow:
  Resolve some issues in mhl Rollang Illig pointed us to:
  Added enhancements from Sergei which he attached to #241.
  Call va_end after the iteration as we need to free the list again.
  Fixing a theoretical buffer overflow which was reported by Roland Illig

Conflicts:
	mhl/types.h

Signed-off-by: Patrick Winnertz <winnie@debian.org>
2009-02-04 12:42:58 +01:00

153 lines
3.2 KiB
C

#ifndef MHL_ESCAPE_H
#define MHL_ESCAPE_H
/* Micro helper library: shell escaping functions */
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define mhl_shell_escape_toesc(x) \
(((x)==' ')||((x)=='!')||((x)=='#')||((x)=='$')||((x)=='%')|| \
((x)=='(')||((x)==')')||((x)=='\'')||((x)=='&')||((x)=='~')|| \
((x)=='{')||((x)=='}')||((x)=='[')||((x)==']')||((x)=='`')|| \
((x)=='?')||((x)=='|')||((x)=='<')||((x)=='>')||((x)==';')|| \
((x)=='*')||((x)=='\\')||((x)=='"'))
#define mhl_shell_escape_nottoesc(x) \
(((x)!=0) && (!mhl_shell_escape_toesc((x))))
/* type for escaped string - just for a bit more type safety ;-p */
typedef struct { char* s; } SHELL_ESCAPED_STR;
/** To be compatible with the general posix command lines we have to escape
strings for the command line
/params const char * in
string for escaping
/returns
return escaped string (later need to free)
*/
static inline SHELL_ESCAPED_STR mhl_shell_escape_dup(const char* src)
{
if ((src==NULL)||(!(*src)))
return (SHELL_ESCAPED_STR){ .s = strdup("") };
char* buffer = calloc(1, strlen(src)*2+2);
char* ptr = buffer;
/* look for the first char to escape */
while (1)
{
char c;
/* copy over all chars not to escape */
while ((c=(*src)) && mhl_shell_escape_nottoesc(c))
{
*ptr = c;
ptr++;
src++;
}
/* at this point we either have an \0 or an char to escape */
if (!c)
return (SHELL_ESCAPED_STR){ .s = buffer };
*ptr = '\\';
ptr++;
*ptr = c;
ptr++;
src++;
}
}
/** Unescape paths or other strings for e.g the internal cd
shell-unescape within a given buffer (writing to it!)
/params const char * src
string for unescaping
/returns
return unescaped string
*/
static inline char* mhl_shell_unescape_buf(char* text)
{
if (!text)
return NULL;
/* look for the first \ - that's quick skipover if there's nothing to escape */
char* readptr = text;
while ((*readptr) && ((*readptr)!='\\')) readptr++;
if (!(*readptr)) return text;
/* if we're here, we're standing on the first '\' */
char* writeptr = readptr;
char c;
while ((c = *readptr))
{
if (c=='\\')
{
readptr++;
switch ((c = *readptr))
{
case 'n': (*writeptr) = '\n'; writeptr++; break;
case 'r': (*writeptr) = '\r'; writeptr++; break;
case 't': (*writeptr) = '\t'; writeptr++; break;
case ' ':
case '\\':
case '#':
case '$':
case '%':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '<':
case '>':
case '!':
case '*':
case '?':
case '~':
case '`':
case '"':
case ';':
case '\0': /* end of string! malformed escape string */
goto out;
default:
(*writeptr) = c; writeptr++; break;
}
}
else /* got a normal character */
{
(*writeptr) = *readptr;
writeptr++;
}
readptr++;
}
out:
*writeptr = 0;
return text;
}
/** Check if char in pointer contain escape'd chars
/params const char * in
string for checking
/returns
return TRUE if string contain escaped chars
otherwise return FALSE
*/
static inline bool
mhl_shell_is_char_escaped ( const char *in )
{
if (in == NULL || !*in || in[0] != '\\')
return false;
if (mhl_shell_escape_toesc(in[1]))
return true;
return false;
}
#endif