Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

security update: add check on improperly encoded input #29

Merged
merged 6 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
security update: add check on improperly encoded input
  • Loading branch information
Steve Kim committed Jun 1, 2022
commit ce7c8a7ac450a823a11b06508ef1eb7441241f81
4 changes: 2 additions & 2 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ clean:
done

distclean: clean
@for DIR in src examples; do \
@for DIR in src examples tests; do \
echo "===> $${DIR}"; \
(cd $${DIR}; make clean; ${RM} -f Makefile); \
(cd $${DIR}; make clean; ${RM} Makefile); \
echo "<=== $${DIR}"; \
done
${RM} -rf autom4te.cache
Expand Down
3 changes: 2 additions & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -2065,7 +2065,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu

ac_config_headers="$ac_config_headers config.h"

ac_config_files="$ac_config_files Makefile src/qdecoder.pc src/Makefile examples/Makefile"
ac_config_files="$ac_config_files Makefile src/qdecoder.pc src/Makefile examples/Makefile tests/Makefile"


## Set path
Expand Down Expand Up @@ -5006,6 +5006,7 @@ do
"src/qdecoder.pc") CONFIG_FILES="$CONFIG_FILES src/qdecoder.pc" ;;
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
"examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
"tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;

*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ AC_DEFUN([Q_ARG_DISABLE], [
AC_INIT([qDecoder], [12 RELEASE], [http://www.qdecoder.org/])
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADER([config.h])
AC_CONFIG_FILES([Makefile src/qdecoder.pc src/Makefile examples/Makefile])
AC_CONFIG_FILES([Makefile src/qdecoder.pc src/Makefile examples/Makefile tests/Makefile])

## Set path
PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
Expand Down
12 changes: 9 additions & 3 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
Expand All @@ -49,7 +50,7 @@
#include "compat/msw_missing.h"
#endif

// Change two hex character to one hex value.
// Change two hex characters to one hex value.
char _q_x2c(char hex_up, char hex_low)
{
char digit;
Expand Down Expand Up @@ -140,8 +141,13 @@ size_t _q_urldecode(char *str)
break;
}
case '%': {
*pBinPt++ = _q_x2c(*(pEncPt + 1), *(pEncPt + 2));
pEncPt += 2;
if (*(pEncPt + 1) != '\0' && isxdigit(*(pEncPt + 1)) \
&& *(pEncPt + 2) != '\0' && isxdigit(*(pEncPt + 2))) {
*pBinPt++ = _q_x2c(*(pEncPt + 1), *(pEncPt + 2));
pEncPt += 2;
} else {
*pBinPt++ = *pEncPt;
}
break;
}
default: {
Expand Down
62 changes: 62 additions & 0 deletions tests/Makefile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
################################################################################
## qDecoder - http://www.qdecoder.org
##
## Copyright (c) 2000-2022 Seungyoung Kim.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are met:
##
## 1. Redistributions of source code must retain the above copyright notice,
## this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright notice,
## this list of conditions and the following disclaimer in the documentation
## and/or other materials provided with the distribution.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
## POSSIBILITY OF SUCH DAMAGE.
################################################################################

prefix = @prefix@
exec_prefix = @exec_prefix@

## qDecoder definitions
QDECODER_INCDIR = ../src
QDECODER_LIBDIR = ../src

## Compiler options
CC = @CC@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@ -I${QDECODER_INCDIR}

TARGETS = \
test_q_urldecode
QUNIT_OBJ = qunit.o
LIBQDECODER = ${QDECODER_LIBDIR}/libqdecoder.a

## Main
all: ${TARGETS}

run: test
test: all
@./launcher.sh ${TARGETS}

test_q_urldecode: test_q_urldecode.o ${QUNIT_OBJ}
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ test_q_urldecode.o ${QUNIT_OBJ} ${LIBQDECODER}

## Clear Module
clean:
${RM} -f *.o ${TARGETS}

## Compile Module
.c.o:
${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
37 changes: 37 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
qDecoder Unit Tests
===================

# How to run unit tests.

```
$ make test
Test internal.c/_q_urldecode
======================================================================
* TEST : Test plain string . OK (1 assertions, 0ms)
* TEST : Test urlencoded string . OK (1 assertions, 0ms)
* TEST : Test urlencoded string exceptions .. OK (2 assertions, 0ms)
======================================================================
PASS - 3/3 tests passed.
```

# How to write unit tests

We need your help in writing unit tests. Please refer qunit.h for your reference.

```C
#include "qunit.h"
#include "qdecoder.h"

QUNIT_START("Test title");

TEST("Test name1") {
ASSERT_EQUAL_STR("abc", "abc");
ASSERT_EQUAL_INT(8, 8);
}

TEST("Test name2") {
ASSERT_EQUAL_PT(NULL == NULL);
}

QUNIT_END();
```
37 changes: 37 additions & 0 deletions tests/launcher.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/sh

if [ $# = 0 ]; then
echo "This program is called by make. Please use \"make test\" command instead."
exit 1
fi

FAIL=0
FAILDESC=""
for EXECUTABLE in $*; do
./$EXECUTABLE
if [ $? != 0 ]; then
FAIL=1
FAILDESC="$FAILDESC $EXECUTABLE"
fi
echo ""
done

if [ $FAIL != 0 ]; then
echo "======================================================================"
echo "**** OOOOOPS!!! UNSUCESSFUL UNIT TEST FOUND. PLEASE FIX AND RERUN ****"
echo "======================================================================"
echo "Fails in =>$FAILDESC"
exit 1
fi

echo "======================================================================"
echo "**** Good job! All tests are successful ****"
echo "======================================================================"
echo "* ____ _ All tests have finished successfully. *"
echo "* / ___| ___ ___ __| | | | ___ | |__ | | *"
echo "* | | _ / _ \ / _ \ / _\` | _ | |/ _ \| '_ \ | | *"
echo "* | |_| | (_) | (_) | (_| | | |_| | (_) | |_) | |_| *"
echo "* \____|\___/ \___/ \__,_| \___/ \___/|_.__/ (_) *"
echo "======================================================================"
echo "Tested: $*"
exit 0
42 changes: 42 additions & 0 deletions tests/qunit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/******************************************************************************
* qunit - C Unit Test Framework
*
* Copyright (c) 2014-2022 Seungyoung Kim.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/

#include <stdio.h>
#include <sys/time.h>

/**
* Returns the current time in milliseconds.
*
* @return current time in milliseconds.
*/
long _qunit_current_milli(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
long time = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
return time;
}
127 changes: 127 additions & 0 deletions tests/qunit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/******************************************************************************
* qunit - C Unit Test Framework
*
* Copyright (c) 2014-2022 Seungyoung Kim.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/

/**
* qunit C Unit Test Framework.
*
* @file qunit.h
*/

#ifndef QUNIT_H
#define QUNIT_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/time.h>

#ifdef __cplusplus
extern "C" {
#endif

extern long _qunit_current_milli(void);

#define OUTSTREAM (stdout)
#define PRINT(fmt, args...) do { \
fprintf(OUTSTREAM, "" fmt, ##args); \
} while(0)
#define PRINTLN(fmt, args...) do { \
fprintf(OUTSTREAM, "" fmt "\n", ##args); \
} while(0)

#define QUNIT_START(title) \
char *_q_title = title; \
int _q_tot_tests = 0; \
int _q_tot_failed = 0; \
int _q_this_failed = 0; \
int _q_errcnt = 0; \
int _q_assert_cnt = 0; /* number of assert test in a test */ \
int _q_assert_dot_cnt = 0; /* number of dots printed out in a test. */ \
long _q_timer; \
int main(int argc, char **argv) { \
PRINTLN("%s", _q_title); \
PRINTLN("======================================================================"); \

#define QUNIT_END() \
_TEST_RESULT(); \
PRINTLN("======================================================================"); \
PRINTLN("%s - %d/%d tests passed.", \
((_q_tot_failed == 0) ? "PASS" : "FAIL"), \
(_q_tot_tests - _q_tot_failed), _q_tot_tests); \
return _q_tot_failed; \
}

#define TEST(name) \
_TEST_RESULT(); \
_q_tot_tests++; \
_q_assert_cnt = 0; \
_q_assert_dot_cnt = 0; \
PRINT("* TEST : %s ", name); \
TIMER_START(_q_timer);

#define _TEST_RESULT() \
TIMER_STOP(_q_timer); \
if (_q_tot_tests ) PRINTLN(" %s (%d assertions, %ldms)", \
(_q_this_failed) ? "FAIL" : "OK", _q_assert_cnt, _q_timer); \
_q_tot_failed += (_q_this_failed) ? 1 : 0; \
_q_this_failed = 0;

#define ASSERT(expr) \
_q_assert_cnt++; \
if (! (expr)) { \
_q_this_failed++; \
PRINTLN("\nAssertion '%s' failed (%s:%d)", #expr, __FILE__, __LINE__); \
} else if (_q_assert_dot_cnt < 30) { \
PRINT("."); \
_q_assert_dot_cnt++; \
}

#define ASSERT_EQUAL_STR(s1, s2) ASSERT(!strcmp(s1, s2))
#define ASSERT_EQUAL_INT(d1, d2) ASSERT(d1 == d2)
#define ASSERT_EQUAL_BOOL(d1, d2) ASSERT(d1 == d2)
#define ASSERT_EQUAL_PT(p1, p2) ASSERT(p1 == p2)
#define ASSERT_EQUAL_MEM(p1, p2, n) ASSERT(!memcmp(p1, p2, n))
#define ASSERT_NULL(p) ASSERT(NULL == p)
#define ASSERT_NOT_NULL(p) ASSERT(NULL != p)
#define ASSERT_TRUE(b) ASSERT(b)
#define ASSERT_FALSE(b) ASSERT(!(b))

#define TIMER_START(x) do { \
x = _qunit_current_milli(); \
} while(0)

#define TIMER_STOP(x) do { \
x = _qunit_current_milli() - x; \
} while(0)

#ifdef __cplusplus
}
#endif

#endif /* QUNIT_H */
Loading