📄 int_string.c
字号:
/****************************************************************************
* *
* cryptlib Internal String API *
* Copyright Peter Gutmann 1992-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#else
#include "crypt.h"
#endif /* Compiler-specific includes */
/****************************************************************************
* *
* General-purpose String Functions *
* *
****************************************************************************/
/* Perform various string-processing operations */
CHECK_RETVAL_STRINGOP( strLen ) STDC_NONNULL_ARG( ( 1 ) ) \
int strFindCh( IN_BUFFER( strLen ) const char *str,
IN_LENGTH_SHORT const int strLen,
IN_CHAR const int findCh )
{
int i;
assert( isReadPtr( str, strLen ) );
REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
REQUIRES( findCh >= 0 && findCh <= 0x7F );
for( i = 0; i < strLen; i++ )
{
if( str[ i ] == findCh )
return( i );
}
return( -1 );
}
CHECK_RETVAL_STRINGOP( strLen ) STDC_NONNULL_ARG( ( 1, 3 ) ) \
int strFindStr( IN_BUFFER( strLen ) const char *str,
IN_LENGTH_SHORT const int strLen,
IN_BUFFER( findStrLen ) const char *findStr,
IN_LENGTH_SHORT const int findStrLen )
{
const int findCh = toUpper( findStr[ 0 ] );
int i;
assert( isReadPtr( str, strLen ) );
assert( isReadPtr( findStr, findStrLen ) );
REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
REQUIRES( findStrLen > 0 && findStrLen < MAX_INTLENGTH_SHORT );
REQUIRES( findCh >= 0 && findCh <= 0x7F );
for( i = 0; i <= strLen - findStrLen; i++ )
{
if( toUpper( str[ i ] ) == findCh && \
!strCompare( str + i, findStr, findStrLen ) )
return( i );
}
return( -1 );
}
CHECK_RETVAL_STRINGOP( strLen ) STDC_NONNULL_ARG( ( 1 ) ) \
int strSkipWhitespace( IN_BUFFER( strLen ) const char *str,
IN_LENGTH_SHORT const int strLen )
{
int i;
assert( isReadPtr( str, strLen ) );
REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
for( i = 0; i < strLen && ( str[ i ] == ' ' || str[ i ] == '\t' ); i++ );
return( ( i < strLen ) ? i : -1 );
}
CHECK_RETVAL_STRINGOP( strLen ) STDC_NONNULL_ARG( ( 1 ) ) \
int strSkipNonWhitespace( IN_BUFFER( strLen ) const char *str,
IN_LENGTH_SHORT const int strLen )
{
int i;
assert( isReadPtr( str, strLen ) );
REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
/* This differs slightly from strSkipWhitespace() in that EOL is also
counted as whitespace so there's never an error condition unless
we don't find anything at all */
for( i = 0; i < strLen && str[ i ] != ' ' && str[ i ] != '\t'; i++ );
return( i > 0 ? i : -1 );
}
CHECK_RETVAL_STRINGOP( strLen ) STDC_NONNULL_ARG( ( 1, 2 ) ) \
int strStripWhitespace( OUT_PTR char **newStringPtr,
IN_BUFFER( strLen ) const char *string,
IN_LENGTH_SHORT const int strLen )
{
int startPos, endPos;
assert( isWritePtr( newStringPtr, sizeof( char * ) ) );
assert( isReadPtr( string, strLen ) );
REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
/* Clear return value */
*newStringPtr = NULL;
/* Skip leading and trailing whitespace */
for( startPos = 0;
startPos < strLen && \
( string[ startPos ] == ' ' || string[ startPos ] == '\t' );
startPos++ );
if( startPos >= strLen )
return( -1 );
*newStringPtr = ( char * ) string + startPos;
for( endPos = strLen;
endPos > startPos && \
( string[ endPos - 1 ] == ' ' || string[ endPos - 1 ] == '\t' );
endPos-- );
ENSURES( endPos - startPos > 0 );
return( endPos - startPos );
}
/****************************************************************************
* *
* Special-purpose String Functions *
* *
****************************************************************************/
/* Extract a substring from a string. This converts:
string startOffset strLen
| | |
v v v
+-------------------+---------------+-------------------+
| Processed data | Whitespace | Remaining data |
+-------------------+---------------+-------------------+
into:
newStr length
| |
v v
+-------------------+
| Remaining data |
+-------------------+
The order of the parameters is a bit unusual, normally we'd use
{ str, strLen } but this makes things a bit confusing for the caller, for
whom it's more logical to group the parameters based on the overall
operation beingn performed, which to extract a substring beginning at
startOffset is { str, startOffset, strLen } */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int strExtract( OUT_PTR char **newStringPtr,
IN_BUFFER( srcLen ) const char *string,
IN_LENGTH_SHORT const int startOffset,
IN_LENGTH_SHORT const int strLen )
{
const int newLen = strLen - startOffset;
assert( isWritePtr( newStringPtr, sizeof( char * ) ) );
assert( isReadPtr( string, strLen ) );
REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
REQUIRES( startOffset >= 0 && startOffset <= strLen && \
startOffset < MAX_INTLENGTH_SHORT );
/* May be zero if we're extracting from the start of the
string; may be equal to strLen if it's the entire
remaining string */
if( newLen < 1 || newLen > strLen || newLen >= MAX_INTLENGTH_SHORT )
return( -1 );
return( strStripWhitespace( newStringPtr, string + startOffset, newLen ) );
}
/* Parse a numeric string into an integer value. Safe conversion of a
numeric string gets a bit problematic because atoi() can't really
indicate an error except by returning 0, which is indistinguishable from
a zero numeric value. To handle this we have to perform the conversion
ourselves */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int strGetNumeric( IN_BUFFER( strLen ) const char *str,
IN_LENGTH_SHORT const int strLen,
OUT_INT_Z int *numericValue,
IN_RANGE( 0, 100 ) const int minValue,
IN_RANGE( minValue, MAX_INTLENGTH ) const int maxValue )
{
int i, value = 0;
assert( isReadPtr( str, strLen ) );
assert( isWritePtr( numericValue, sizeof( int ) ) );
REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
REQUIRES( minValue >= 0 && minValue < maxValue && \
maxValue <= MAX_INTLENGTH );
/* Clear return value */
*numericValue = 0;
/* Make sure that the value is within the range 'n' ... 'nnnnnnn' */
if( strLen < 1 || strLen > 7 )
return( CRYPT_ERROR_BADDATA );
/* Process the numeric string */
for( i = 0; i < strLen; i++ )
{
const int ch = str[ i ] - '0';
if( ch < 0 || ch > 9 )
return( CRYPT_ERROR_BADDATA );
value = ( value * 10 ) + ch;
}
if( value < 0 || value < minValue || \
value > MAX_INTLENGTH || value > maxValue )
return( CRYPT_ERROR_BADDATA );
*numericValue = value;
return( CRYPT_OK );
}
/* Sanitise a string before passing it back to the user. This is used to
clear potential problem characters (for example control characters)
from strings passed back from untrusted sources. The function returns a
pointer to the string to allow it to be used in the form
printf( "..%s..", sanitiseString( string, strLen ) ). In addition it
formats the data to fit a fixed-length buffer, if the string is longer
than the indicated buffer size then it appends a '[...]' at the end of
the buffer to indicate that further data was truncated. The
transformation applied is as follows:
buffer strMaxLen
| |
v v
+---------------------------+ . .
| | ==> . .
+---------------------------+ . .
. . . .
|---------------| . |---------------|\0| .
. ^ . . .
|--------------------------------| |-----------------------|[...]\0|
| ^
+---- strLen ----+
so "Error string of arbitrary length..." with a buffer size of 20 would
become "Error string [...]" */
STDC_NONNULL_ARG( ( 1 ) ) \
char *sanitiseString( INOUT_BUFFER_FIXED( strMaxLen ) BYTE *string,
IN_LENGTH_SHORT const int strMaxLen,
IN_LENGTH_SHORT const int strLen )
{
const int strDataLen = min( strLen, strMaxLen );
int i;
assert( isWritePtr( string, strMaxLen ) );
REQUIRES_EXT( ( strLen > 0 && strLen < MAX_INTLENGTH_SHORT ), \
"(Internal error)" );
REQUIRES_EXT( ( strMaxLen > 0 && strMaxLen < MAX_INTLENGTH_SHORT ), \
"(Internal error)" );
/* Remove any potentially unsafe characters from the string, effectively
converting it from a 'BYTE *' to a 'char *' */
for( i = 0; i < strDataLen; i++ )
{
const int ch = string[ i ];
if( ch <= 0 || ch > 0x7F || !isPrint( ch ) )
string[ i ] = '.';
}
/* If there was more input than we could fit into the buffer and
there's room for a continuation indicator, add this to the output
string */
if( ( strLen > strMaxLen ) && ( strMaxLen > 8 ) )
memcpy( string + strMaxLen - 6, "[...]", 5 ); /* Extra -1 for '\0' */
/* Terminate the string to allow it to be used in printf()-style
functions */
if( strLen < strMaxLen )
string[ strLen ] = '\0';
else
string[ strMaxLen - 1 ] = '\0';
/* We've converted the string from BYTE * to char * so it can be
returned as a standard text string */
return( ( char * ) string );
}
/****************************************************************************
* *
* TR 24731 Safe stdlib Extensions *
* *
****************************************************************************/
#ifndef __STDC_LIB_EXT1__
/* Minimal wrappers for the TR 24731 functions to map them to older stdlib
equivalents. Because of potential issues when comparing a (signed)
literal value -1 to the unsigned size_t we explicitly check for both
'( size_t ) -1' as well as a general check for a negative return value */
RETVAL_RANGE( -1, 0 ) \
int mbstowcs_s( OUT size_t *retval,
OUT_BUFFER_FIXED( dstmax ) wchar_t *dst,
IN_LENGTH_SHORT size_t dstmax,
IN_BUFFER( len ) const char *src,
IN_LENGTH_SHORT size_t len )
{
size_t bytesCopied;
assert( isWritePtr( retval, sizeof( size_t ) ) );
assert( isWritePtr( dst, dstmax ) );
assert( isReadPtr( src, len ) );
REQUIRES_EXT( ( dstmax > 0 && dstmax < MAX_INTLENGTH_SHORT ), -1 );
REQUIRES_EXT( ( len > 0 && len <= dstmax && \
len < MAX_INTLENGTH_SHORT ), -1 );
/* Clear return value */
*retval = 0;
bytesCopied = mbstowcs( dst, src, len );
if( ( bytesCopied == ( size_t ) -1 ) || ( bytesCopied <= 0 ) )
return( -1 );
*retval = bytesCopied;
return( 0 );
}
RETVAL_RANGE( -1, 0 ) \
int wcstombs_s( OUT size_t *retval,
OUT_BUFFER_FIXED( dstmax ) char *dst,
IN_LENGTH_SHORT size_t dstmax,
IN_BUFFER( len) const wchar_t *src,
IN_LENGTH_SHORT size_t len )
{
size_t bytesCopied;
assert( isWritePtr( retval, sizeof( size_t ) ) );
assert( isWritePtr( dst, dstmax ) );
assert( isReadPtr( src, len ) );
REQUIRES_EXT( ( dstmax > 0 && dstmax < MAX_INTLENGTH_SHORT ), -1 );
REQUIRES_EXT( ( len > 0 && len <= dstmax && \
len < MAX_INTLENGTH_SHORT ), -1 );
/* Clear return value */
*retval = 0;
bytesCopied = wcstombs( dst, src, len );
if( ( bytesCopied == ( size_t ) -1 ) || ( bytesCopied <= 0 ) )
return( -1 );
*retval = bytesCopied;
return( 0 );
}
#endif /* !__STDC_LIB_EXT1__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -