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

Fix for #85 and #86 #87

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 3 additions & 1 deletion lib/component.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ UnshieldComponent* unshield_component_new(Header* header, uint32_t offset)

self->file_group_count = READ_UINT16(p); p += 2;
if (self->file_group_count > MAX_FILE_GROUP_COUNT)
abort();
{
UNSHIELD_THROW_EXCEPTION(&header->exception, "file_group_count > MAX_FILE_GROUP_COUNT");
}

self->file_group_names = NEW(const char*, self->file_group_count);

Expand Down
10 changes: 8 additions & 2 deletions lib/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,17 @@ bool unshield_read_common_header(uint8_t** buffer, CommonHeader* common)
*/
uint8_t* unshield_header_get_buffer(Header* header, uint32_t offset)
{
if (offset)
return
if (offset){
if (header->common.cab_descriptor_offset + offset > header->size)
{
UNSHIELD_THROW_EXCEPTION(&header->exception, "cab_descriptor_offset + offset > header->size");
}

return
header->data +
header->common.cab_descriptor_offset +
offset;
}
else
return NULL;
}
Expand Down
27 changes: 26 additions & 1 deletion lib/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,22 @@
#include <inttypes.h>
#endif

#include <setjmp.h>
#include <stdbool.h>
#include <stdio.h> /* for FILE */

#include "cabfile.h"

typedef struct _Exception Exception;

struct _Exception
{
jmp_buf environment;
const char* function;
int line;
const char* message;
};

typedef struct _StringBuffer StringBuffer;

struct _StringBuffer
Expand All @@ -28,6 +39,7 @@ typedef struct _Header Header;

struct _Header
{
Exception exception;
Header* next;
int index;
uint8_t* data;
Expand Down Expand Up @@ -63,7 +75,7 @@ UnshieldComponent* unshield_component_new(Header* header, uint32_t offset);
void unshield_component_destroy(UnshieldComponent* self);


/*
/*
Internal file group functions
*/

Expand All @@ -84,6 +96,19 @@ const char* unshield_header_get_string(Header* header, uint32_t offset);
uint8_t* unshield_header_get_buffer(Header* header, uint32_t offset);


#define UNSHIELD_HANDLE_EXCEPTION(e) (setjmp(e.environment) != 0)

static inline void _unshield_throw_exception(Exception* exception, const char* function, int line, const char* message)
{
exception->function = function;
exception->line = line;
exception->message = message;
longjmp(exception->environment, 1);
}

#define UNSHIELD_THROW_EXCEPTION(exception, message) { _unshield_throw_exception(exception, __FUNCTION__, __LINE__, message); }


/*
Constants
*/
Expand Down
6 changes: 6 additions & 0 deletions lib/libunshield.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ static bool unshield_read_headers(Unshield* unshield, int version)/*{{{*/
Header* header = NEW1(Header);
header->index = i;

if (UNSHIELD_HANDLE_EXCEPTION(header->exception)) {
unshield_error("An exception occurred while reading .hdr file %i: [%s:%i] %s",
i, header->exception.function, header->exception.line, header->exception.message);
goto error;
}

header->size = FSIZE(file);
if (header->size < 4)
{
Expand Down
Binary file added test/bugs/debian-776238/data1.cab
Binary file not shown.
Binary file added test/bugs/debian-776238/data1.hdr
Binary file not shown.
35 changes: 35 additions & 0 deletions test/bugs/debian-776238/debian-776238.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash
set -e
cd `dirname $0`
MD5_FILE=`pwd`/`basename $0 .sh`.md5
CAB_FILE=`pwd`/data1.cab
UNSHIELD=${UNSHIELD:-/var/tmp/unshield/bin/unshield}

if [ \! -x ${UNSHIELD} ]; then
echo "unshield executable not found at $UNSHIELD" >&2
exit 1
fi

DIR=`mktemp -d`
#trap 'rm -rf ${DIR}' TERM INT EXIT
cd ${DIR}

set +e
rm -f /tmp/moo

timeout 10 ${UNSHIELD} -d extract1 x "$CAB_FILE" > log1 2>&1
CODE=$?
if [ -e /tmp/moo ]; then
cat log1 >&2
echo "unshield vulnerable to CVE-2015-1386" >&2
echo "See https://github.com/twogood/unshield/issues/42" >&2
exit 2
fi

if [ ${CODE} -ne 1 ]; then
cat log1 >&2
echo "unshield should have failed with error 1 but was $CODE" >&2
exit 3
fi

exit 0
Binary file added test/bugs/debian-776239/data1.cab
Binary file not shown.
Binary file added test/bugs/debian-776239/data1.hdr
Binary file not shown.
35 changes: 35 additions & 0 deletions test/bugs/debian-776239/debian-776239.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash
set -e
cd `dirname $0`
MD5_FILE=`pwd`/`basename $0 .sh`.md5
CAB_FILE=`pwd`/data1.cab
UNSHIELD=${UNSHIELD:-/var/tmp/unshield/bin/unshield}

if [ \! -x ${UNSHIELD} ]; then
echo "unshield executable not found at $UNSHIELD" >&2
exit 1
fi

DIR=`mktemp -d`
#trap 'rm -rf ${DIR}' TERM INT EXIT
cd ${DIR}

set +e
rm -f /tmp/moo

timeout 10 ${UNSHIELD} -d extract1 x "$CAB_FILE" > log1 2>&1
CODE=$?
if [ -e /tmp/moo ]; then
cat log1 >&2
echo "unshield vulnerable to CVE-2015-1386" >&2
echo "See https://github.com/twogood/unshield/issues/42" >&2
exit 2
fi

if [ ${CODE} -ne 1 ]; then
cat log1 >&2
echo "unshield should have failed with error 1 but was $CODE" >&2
exit 3
fi

exit 0