Basic Bugs in Demo Application

A demo giftcardreader application was given. here is how I discovered the bugs

2 crashes and 1 infinite loop discovery:

Bug description:

crash1.gft => I discovered a crash by putting data length = -1 in gengift.py. This crashes the code at line at 198 where it tries to allocate memory. Since, program can't allocate negative memory, I fixed it by adding a check for negative number of bytes. Program exits if it detects negative number of bytes.

crash2.gft => type of record 3 in the gengift file crashes code at line 254 and then at line 260 because then it tries to allocate memory that is out of bounds. Non-animated gift card allocates a memory lesser than 256 bytes and animated gift card allocates 256 bytes plus. So, I added a check, if number of bytes are more than 255, it will only then execute the part where animated gift card is processed by pointers. Or else exits.

hang.gft => I discovered an infinite loop in genanim.py -> program data section by refering the lecture and adding \x09\xfd + 254 bytes of B to the data buffer will cause an infinite loop. I fixed it by going to giftcardreader.c in the animate() function and in case of "09" opcode, changed it to unsigned char from original char

Initial giftcardreader.c code:

/*
 * Gift Card Reading Application
 * Original Author: Shoddycorp's Cut-Rate Contracting
 * Comments added by: Justin Cappos (JAC) and Brendan Dolan-Gavitt (BDG)
 * Maintainer:
 * Date: 8 July 2020
 */


#include "giftcard.h"

#include <stdio.h>
#include <string.h>
#include <unistd.h>

// .,~==== interpreter for THX-1138 assembly ====~,.
//
// This is an emulated version of a microcontroller with
// 16 registers, one flag (the zero flag), and display
// functionality. Programs can operate on the message
// buffer and use opcode 0x07 to update the display, so
// that animated greetings can be created.
void animate(char *msg, unsigned char *program) {
    unsigned char regs[16];
    char *mptr = msg; // TODO: how big is this buffer?
    unsigned char *pc = program;
    int i = 0;
    int zf = 0;
    while (pc < program+256) {
        unsigned char op, arg1, arg2;
        op = *pc;
        arg1 = *(pc+1);
        arg2 = *(pc+2);
        switch (*pc) {
            case 0x00:
                break;
            case 0x01:
                regs[arg1] = *mptr;
                break;
            case 0x02:
                *mptr = regs[arg1];
                break;
            case 0x03:
                mptr += (char)arg1;
                break;
            case 0x04:
                regs[arg2] = arg1;
                break;
            case 0x05:
                regs[arg1] ^= regs[arg2];
                zf = !regs[arg1];
                break;
            case 0x06:
                regs[arg1] += regs[arg2];
                zf = !regs[arg1];
                break;
            case 0x07:
                puts(msg);
                break;
            case 0x08:
                goto done;
            case 0x09:
                pc += (char)arg1;
                break;
            case 0x10:
                if (zf) pc += (char)arg1;
                break;
        }
        pc+=3;
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
        // Slow down animation to make it more visible (disabled if fuzzing)
        usleep(5000);
#endif
    }
done:
    return;
}

int get_gift_card_value(struct this_gift_card *thisone) {
	struct gift_card_data *gcd_ptr;
	struct gift_card_record_data *gcrd_ptr;
	struct gift_card_amount_change *gcac_ptr;
	int ret_count = 0;

	gcd_ptr = thisone->gift_card_data;
	for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
  		gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
		if (gcrd_ptr->type_of_record == 1) {
			gcac_ptr = gcrd_ptr->actual_record;
			ret_count += gcac_ptr->amount_added;
		}
	}
	return ret_count;
}

void print_gift_card_info(struct this_gift_card *thisone) {
	struct gift_card_data *gcd_ptr;
	struct gift_card_record_data *gcrd_ptr;
	struct gift_card_amount_change *gcac_ptr;
    struct gift_card_program *gcp_ptr;

	gcd_ptr = thisone->gift_card_data;
	printf("   Merchant ID: %32.32s\n",gcd_ptr->merchant_id);
	printf("   Customer ID: %32.32s\n",gcd_ptr->customer_id);
	printf("   Num records: %d\n",gcd_ptr->number_of_gift_card_records);
	for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
  		gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
		if (gcrd_ptr->type_of_record == 1) {
			printf("      record_type: amount_change\n");
			gcac_ptr = gcrd_ptr->actual_record;
			printf("      amount_added: %d\n",gcac_ptr->amount_added);
			if (gcac_ptr->amount_added>0) {
				printf("      signature: %32.32s\n",gcac_ptr->actual_signature);
			}
		}
		else if (gcrd_ptr->type_of_record == 2) {
			printf("      record_type: message\n");
			printf("      message: %s\n",(char *)gcrd_ptr->actual_record);
		}
		else if (gcrd_ptr->type_of_record == 3) {
            gcp_ptr = gcrd_ptr->actual_record;
			printf("      record_type: animated message\n");
            // BDG: Hmm... is message guaranteed to be null-terminated?
            printf("      message: %s\n", gcp_ptr->message);
            printf("  [running embedded program]  \n");
            animate(gcp_ptr->message, gcp_ptr->program);
		}
	}
	printf("  Total value: %d\n\n",get_gift_card_value(thisone));
}

// Added to support web functionalities
void gift_card_json(struct this_gift_card *thisone) {
    struct gift_card_data *gcd_ptr;
    struct gift_card_record_data *gcrd_ptr;
    struct gift_card_amount_change *gcac_ptr;
    gcd_ptr = thisone->gift_card_data;
    printf("{\n");
    printf("  \"merchant_id\": \"%32.32s\",\n", gcd_ptr->merchant_id);
    printf("  \"customer_id\": \"%32.32s\",\n", gcd_ptr->customer_id);
    printf("  \"total_value\": %d,\n", get_gift_card_value(thisone));
    printf("  \"records\": [\n");
	for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
        gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
        printf("    {\n");
        if (gcrd_ptr->type_of_record == 1) {
            printf("      \"record_type\": \"amount_change\",\n");
            gcac_ptr = gcrd_ptr->actual_record;
            printf("      \"amount_added\": %d,\n",gcac_ptr->amount_added);
            if (gcac_ptr->amount_added>0) {
                printf("      \"signature\": \"%32.32s\"\n",gcac_ptr->actual_signature);
            }
        }
        else if (gcrd_ptr->type_of_record == 2) {
			printf("      \"record_type\": \"message\",\n");
			printf("      \"message\": \"%s\"\n",(char *)gcrd_ptr->actual_record);
        }
        else if (gcrd_ptr->type_of_record == 3) {
            struct gift_card_program *gcp = gcrd_ptr->actual_record;
			printf("      \"record_type\": \"animated message\",\n");
			printf("      \"message\": \"%s\",\n",gcp->message);
            // programs are binary so we will hex for the json
            char *hexchars = "01234567890abcdef";
            char program_hex[512+1];
            program_hex[512] = '\0';
            int i;
            for(i = 0; i < 256; i++) {
                program_hex[i*2] = hexchars[((gcp->program[i] & 0xf0) >> 4)];
                program_hex[i*2+1] = hexchars[(gcp->program[i] & 0x0f)];
            }
			printf("      \"program\": \"%s\"\n",program_hex);
        }
        if (i < gcd_ptr->number_of_gift_card_records-1)
            printf("    },\n");
        else
            printf("    }\n");
    }
    printf("  ]\n");
    printf("}\n");
}


struct this_gift_card *gift_card_reader(FILE *input_fd) {

	struct this_gift_card *ret_val = malloc(sizeof(struct this_gift_card));

    void *optr;
	void *ptr;

	// Loop to do the whole file
	while (!feof(input_fd)) {

		struct gift_card_data *gcd_ptr;
		/* JAC: Why aren't return types checked? */
		fread(&ret_val->num_bytes, 4,1, input_fd);

		// Make something the size of the rest and read it in
		ptr = malloc(ret_val->num_bytes);
		fread(ptr, ret_val->num_bytes, 1, input_fd);

        optr = ptr-4;

		gcd_ptr = ret_val->gift_card_data = malloc(sizeof(struct gift_card_data));
		gcd_ptr->merchant_id = ptr;
		ptr += 32;
//		printf("VD: %d\n",(int)ptr - (int) gcd_ptr->merchant_id);
		gcd_ptr->customer_id = ptr;
		ptr += 32;
		/* JAC: Something seems off here... */
		gcd_ptr->number_of_gift_card_records = *((char *)ptr);
		ptr += 4;

		gcd_ptr->gift_card_record_data = (void *)malloc(gcd_ptr->number_of_gift_card_records*sizeof(void*));

		// Now ptr points at the gift card recrod data
		for (int i=0; i < gcd_ptr->number_of_gift_card_records; i++){
			//printf("i: %d\n",i);
			struct gift_card_record_data *gcrd_ptr;
			gcrd_ptr = gcd_ptr->gift_card_record_data[i] = malloc(sizeof(struct gift_card_record_data));
			struct gift_card_amount_change *gcac_ptr;
			gcac_ptr = gcrd_ptr->actual_record = malloc(sizeof(struct gift_card_record_data));
            struct gift_card_program *gcp_ptr;
			gcp_ptr = malloc(sizeof(struct gift_card_program));

			gcrd_ptr->record_size_in_bytes = *((char *)ptr);
            //printf("rec at %x, %d bytes\n", ptr - optr, gcrd_ptr->record_size_in_bytes);
			ptr += 4;
			//printf("record_data: %d\n",gcrd_ptr->record_size_in_bytes);
			gcrd_ptr->type_of_record = *((char *)ptr);
			ptr += 4;
            //printf("type of rec: %d\n", gcrd_ptr->type_of_record);

			// amount change
			if (gcrd_ptr->type_of_record == 1) {
				gcac_ptr->amount_added = *((int*) ptr);
				ptr += 4;

				// don't need a sig if negative
				/* JAC: something seems off here */
				if (gcac_ptr < 0) break;

				gcac_ptr->actual_signature = ptr;
				ptr+=32;
			}
			// message
			if (gcrd_ptr->type_of_record == 2) {
				gcrd_ptr->actual_record = ptr;
				// advance by the string size + 1 for nul
                // BDG: does not seem right
				ptr=ptr+strlen((char *)gcrd_ptr->actual_record)+1;
			}
            // BDG: gift cards can run code?? Might want to check this one carefully...
            // text animatino (BETA)
            if (gcrd_ptr->type_of_record == 3) {
                gcp_ptr->message = malloc(32);
                gcp_ptr->program = malloc(256);
                memcpy(gcp_ptr->message, ptr, 32);
                ptr+=32;
                memcpy(gcp_ptr->program, ptr, 256);
                ptr+=256;
                gcrd_ptr->actual_record = gcp_ptr;
            }

            if (gcrd_ptr->type_of_record > 3) {
                printf("unknown record type: %d\n", gcrd_ptr->type_of_record);
                exit(1);
            }
		}
	}
	return ret_val;
}

struct this_gift_card *thisone;

int main(int argc, char **argv) {
    if (argc != 3) {
        fprintf(stderr, "usage: %s <1|2> file.gft\n", argv[0]);
        fprintf(stderr, "  - Use 1 for text output, 2 for JSON output\n");
        return 1;
    }
	FILE *input_fd = fopen(argv[2],"r");
    if (!input_fd) {
        fprintf(stderr, "error opening file\n");
        return 1;
    }
	thisone = gift_card_reader(input_fd);
	if (argv[1][0] == '1') print_gift_card_info(thisone);
    else if (argv[1][0] == '2') gift_card_json(thisone);

	return 0;
}

Initial gengift.py code:

To generate a giftcard file: python3 gengift.py name.gft

import struct
import sys

# We build the content of the file in a byte string first
# This lets us calculate the length for the header at the end
data = b''
data += b"GiftCardz.com".ljust(32, b' ') # Merchant ID
data += b"B"*32 # Customer ID
data += struct.pack("<I", 1) # One record
# Record of type message
data += struct.pack("<I", 8 + 32)       # Record size: 4 bytes size, 4 bytes type, 32 bytes message
data += struct.pack("<I", 2)            # Record type
data += b"x"*31 + b'\0'                 # Note: 32 byte message

f = open(sys.argv[1], 'wb')
datalen = len(data) + 4 # Plus 4 bytes for the length itself
f.write(struct.pack("<I", datalen))
f.write(data)
f.close()

Initial genanim.py code:

To generate animated giftcard file: python3 genanim.py animated_name.gft

import struct
import sys

# We build the content of the file in a byte string first
# This lets us calculate the length for the header at the end
data = b''
data += b"A"*32 # Merchant ID
data += b"B"*32 # Customer ID
data += struct.pack("<I", 1) # One record
# Record of type animation
data += struct.pack("<I", 8 + 32 + 256) # Record size (4 bytes)
data += struct.pack("<I", 3)            # Record type (4 bytes)
data += b"A"*31 + b'\x00'               # Note: 32 byte message
data += b'\x08' * 256                   # Program made entirely of "end program" (256 bytes)

f = open(sys.argv[1], 'wb')
datalen = len(data) + 4 # Plus 4 bytes for the length itself
f.write(struct.pack("<I", datalen))
f.write(data)
f.close()

Crash 1 python file:

import struct

import sys



# We build the content of the file in a byte string first

# This lets us calculate the length for the header at the end

data = b''

data += b"GiftCardz.com".ljust(32, b' ') # Merchant ID

data += b"B"*32 # Customer ID

data += struct.pack("<I", 1) # One record

# Record of type message

data += struct.pack("<I", 8 + 32)       # Record size: 4 bytes size, 4 bytes type, 32 bytes message

data += struct.pack("<I", 1)            # Record type

data += b"x"*31 + b'\0'                 # Note: 32 byte message



f = open(sys.argv[1], 'wb')

datalen = -1		 		# crash for -1 data length

f.write(struct.pack("<i", datalen))

f.write(data)

f.close()

Crash 2 Python file

import struct

import sys



# We build the content of the file in a byte string first

# This lets us calculate the length for the header at the end

data = b''

data += b"GiftCardz.com".ljust(32, b' ') # Merchant ID

data += b"B"*32 # Customer ID

data += struct.pack("<I", 1) # One record

# Record of type message

data += struct.pack("<I", 8 + 32)       # Record size: 4 bytes size, 4 bytes type, 32 bytes message

data += struct.pack("<I", 3)            # Record type

data += b"x"*31 + b'\0'                 # Note: 32 byte message



f = open(sys.argv[1], 'wb')

datalen = len(data) + 4 # Plus 4 bytes for the length itself

f.write(struct.pack("<I", datalen))

f.write(data)

f.close()

Hang file python code:

import struct

import sys



# We build the content of the file in a byte string first

# This lets us calculate the length for the header at the end

data = b''

data += b"A"*32 # Merchant ID

data += b"B"*32 # Customer ID

data += struct.pack("<I", 1) # One record

# Record of type animation

data += struct.pack("<I", 8 + 32 + 256) # Record size (4 bytes)

data += struct.pack("<I", 3)            # Record type (4 bytes)

data += b"A"*31 + b'\x00'               # Note: 32 byte message

data += b'\x09\xfd' +b'\x08'* 254       # Program to make it loop infinitely and then random 254 bytes



f = open(sys.argv[1], 'wb')

datalen = len(data) + 4 # Plus 4 bytes for the length itself

f.write(struct.pack("<I", datalen))

f.write(data)

f.close()

Fixed C code:

/*

 * Gift Card Reading Application

 * Original Author: Shoddycorp's Cut-Rate Contracting

 * Comments added by: Justin Cappos (JAC) and Brendan Dolan-Gavitt (BDG)

 * Maintainer:

 * Date: 8 July 2020

 */





#include "giftcard.h"



#include <stdio.h>

#include <string.h>

#include <unistd.h>



// .,~==== interpreter for THX-1138 assembly ====~,.

//

// This is an emulated version of a microcontroller with

// 16 registers, one flag (the zero flag), and display

// functionality. Programs can operate on the message

// buffer and use opcode 0x07 to update the display, so

// that animated greetings can be created.

void animate(char *msg, unsigned char *program) {

    unsigned char regs[16];

    char *mptr = msg; // TODO: how big is this buffer?

    unsigned char *pc = program;

    int i = 0;

    int zf = 0;

    while (pc < program+256) {

        unsigned char op, arg1, arg2;

        op = *pc;

        arg1 = *(pc+1);

        arg2 = *(pc+2);

        switch (*pc) {

            case 0x00:

                break;

            case 0x01:

                regs[arg1] = *mptr;

                break;

            case 0x02:

                *mptr = regs[arg1];

                break;

            case 0x03:

                mptr += (char)arg1;

                break;

            case 0x04:

                regs[arg2] = arg1;

                break;

            case 0x05:

                regs[arg1] ^= regs[arg2];

                zf = !regs[arg1];

                break;

            case 0x06:

                regs[arg1] += regs[arg2];

                zf = !regs[arg1];

                break;

            case 0x07:

                puts(msg);

                break;

            case 0x08:

                goto done;

            case 0x09:

                pc += (unsigned char)arg1; /* fix 3 for hang (infinite loop) */

                break;

            case 0x10:

                if (zf) pc += (char)arg1;

                break;

        }

        pc+=3;

#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION

        // Slow down animation to make it more visible (disabled if fuzzing)

        usleep(5000);

#endif

    }

done:

    return;

}



int get_gift_card_value(struct this_gift_card *thisone) {

	struct gift_card_data *gcd_ptr;

	struct gift_card_record_data *gcrd_ptr;

	struct gift_card_amount_change *gcac_ptr;

	int ret_count = 0;



	gcd_ptr = thisone->gift_card_data;

	for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {

  		gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];

		if (gcrd_ptr->type_of_record == 1) {

			gcac_ptr = gcrd_ptr->actual_record;

			ret_count += gcac_ptr->amount_added;

		}

	}

	return ret_count;

}



void print_gift_card_info(struct this_gift_card *thisone) {

	struct gift_card_data *gcd_ptr;

	struct gift_card_record_data *gcrd_ptr;

	struct gift_card_amount_change *gcac_ptr;

    struct gift_card_program *gcp_ptr;



	gcd_ptr = thisone->gift_card_data;

	printf("   Merchant ID: %32.32s\n",gcd_ptr->merchant_id);

	printf("   Customer ID: %32.32s\n",gcd_ptr->customer_id);

	printf("   Num records: %d\n",gcd_ptr->number_of_gift_card_records);

	for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {

  		gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];

		if (gcrd_ptr->type_of_record == 1) {

			printf("      record_type: amount_change\n");

			gcac_ptr = gcrd_ptr->actual_record;

			printf("      amount_added: %d\n",gcac_ptr->amount_added);

			if (gcac_ptr->amount_added>0) {

				printf("      signature: %32.32s\n",gcac_ptr->actual_signature);

			}

		}

		else if (gcrd_ptr->type_of_record == 2) {

			printf("      record_type: message\n");

			printf("      message: %s\n",(char *)gcrd_ptr->actual_record);

		}

		else if (gcrd_ptr->type_of_record == 3) {

            gcp_ptr = gcrd_ptr->actual_record;

			printf("      record_type: animated message\n");

            // BDG: Hmm... is message guaranteed to be null-terminated?

            printf("      message: %s\n", gcp_ptr->message);

            printf("  [running embedded program]  \n");

            animate(gcp_ptr->message, gcp_ptr->program);

		}

	}

	printf("  Total value: %d\n\n",get_gift_card_value(thisone));

}



// Added to support web functionalities

void gift_card_json(struct this_gift_card *thisone) {

    struct gift_card_data *gcd_ptr;

    struct gift_card_record_data *gcrd_ptr;

    struct gift_card_amount_change *gcac_ptr;

    gcd_ptr = thisone->gift_card_data;

    printf("{\n");

    printf("  \"merchant_id\": \"%32.32s\",\n", gcd_ptr->merchant_id);

    printf("  \"customer_id\": \"%32.32s\",\n", gcd_ptr->customer_id);

    printf("  \"total_value\": %d,\n", get_gift_card_value(thisone));

    printf("  \"records\": [\n");

	for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {

        gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];

        printf("    {\n");

        if (gcrd_ptr->type_of_record == 1) {

            printf("      \"record_type\": \"amount_change\",\n");

            gcac_ptr = gcrd_ptr->actual_record;

            printf("      \"amount_added\": %d,\n",gcac_ptr->amount_added);

            if (gcac_ptr->amount_added>0) {

                printf("      \"signature\": \"%32.32s\"\n",gcac_ptr->actual_signature);

            }

        }

        else if (gcrd_ptr->type_of_record == 2) {

			printf("      \"record_type\": \"message\",\n");

			printf("      \"message\": \"%s\"\n",(char *)gcrd_ptr->actual_record);

        }

        else if (gcrd_ptr->type_of_record == 3) {

            struct gift_card_program *gcp = gcrd_ptr->actual_record;

			printf("      \"record_type\": \"animated message\",\n");

			printf("      \"message\": \"%s\",\n",gcp->message);

            // programs are binary so we will hex for the json

            char *hexchars = "01234567890abcdef";

            char program_hex[512+1];

            program_hex[512] = '\0';

            int i;

            for(i = 0; i < 256; i++) {

                program_hex[i*2] = hexchars[((gcp->program[i] & 0xf0) >> 4)];

                program_hex[i*2+1] = hexchars[(gcp->program[i] & 0x0f)];

            }

			printf("      \"program\": \"%s\"\n",program_hex);

        }

        if (i < gcd_ptr->number_of_gift_card_records-1)

            printf("    },\n");

        else

            printf("    }\n");

    }

    printf("  ]\n");

    printf("}\n");

}





struct this_gift_card *gift_card_reader(FILE *input_fd) {



	struct this_gift_card *ret_val = malloc(sizeof(struct this_gift_card));



    void *optr;

	void *ptr;



	// Loop to do the whole file

	while (!feof(input_fd)) {



		struct gift_card_data *gcd_ptr;

		/* JAC: Why aren't return types checked? */

		fread(&ret_val->num_bytes, 4,1, input_fd);



		/* fix for crash 1 -> number bytes = -1 */



		if (ret_val->num_bytes<0){ //if statement to fix the crashes

			printf("Invalid byte value! Exiting now...");

			printf("\n");

			exit(0);

		}



		// Make something the size of the rest and read it in

		ptr = malloc(ret_val->num_bytes);

		fread(ptr, ret_val->num_bytes, 1, input_fd);



        optr = ptr-4;



		gcd_ptr = ret_val->gift_card_data = malloc(sizeof(struct gift_card_data));

		gcd_ptr->merchant_id = ptr;

		ptr += 32;

//		printf("VD: %d\n",(int)ptr - (int) gcd_ptr->merchant_id);

		gcd_ptr->customer_id = ptr;

		ptr += 32;

		/* JAC: Something seems off here... */

		gcd_ptr->number_of_gift_card_records = *((int *)ptr);

		ptr += 4;



		gcd_ptr->gift_card_record_data = (void *)malloc(gcd_ptr->number_of_gift_card_records*sizeof(void*));



		// Now ptr points at the gift card recrod data

		for (int i=0; i < gcd_ptr->number_of_gift_card_records; i++){

			//printf("i: %d\n",i);

			struct gift_card_record_data *gcrd_ptr;

			gcrd_ptr = gcd_ptr->gift_card_record_data[i] = malloc(sizeof(struct gift_card_record_data));

			struct gift_card_amount_change *gcac_ptr;

			gcac_ptr = gcrd_ptr->actual_record = malloc(sizeof(struct gift_card_record_data));

            struct gift_card_program *gcp_ptr;

			gcp_ptr = malloc(sizeof(struct gift_card_program));



			gcrd_ptr->record_size_in_bytes = *((char *)ptr);

            //printf("rec at %x, %d bytes\n", ptr - optr, gcrd_ptr->record_size_in_bytes);

			ptr += 4;

			//printf("record_data: %d\n",gcrd_ptr->record_size_in_bytes);

			gcrd_ptr->type_of_record = *((char *)ptr);

			ptr += 4;

            //printf("type of rec: %d\n", gcrd_ptr->type_of_record);



			// amount change

			if (gcrd_ptr->type_of_record == 1) {

				gcac_ptr->amount_added = *((int*) ptr);

				ptr += 4;



				// don't need a sig if negative

				/* JAC: something seems off here */

				if (gcac_ptr < 0) break;



				gcac_ptr->actual_signature = ptr;

				ptr+=32;

			}

			// message

			if (gcrd_ptr->type_of_record == 2) {

				gcrd_ptr->actual_record = ptr;

				// advance by the string size + 1 for nul

                // BDG: does not seem right

				ptr=ptr+strlen((char *)gcrd_ptr->actual_record)+1;

			}

            // BDG: gift cards can run code?? Might want to check this one carefully...

            // text animatino (BETA)

            

            /* fix for crash 2 */

            

            if (gcrd_ptr->type_of_record == 3 && ret_val->num_bytes > 255 ) {

                gcp_ptr->message = malloc(32);

                gcp_ptr->program = malloc(256);

                memcpy(gcp_ptr->message, ptr, 32);

                ptr+=32;

                memcpy(gcp_ptr->program, ptr, 256);

                ptr+=256;

                gcrd_ptr->actual_record = gcp_ptr;

            }

            else{

            	printf("Invalid record type for the specified gift card! Exiting...\n");

            	exit(1);

            }



            if (gcrd_ptr->type_of_record > 3) {

                printf("unknown record type: %d\n", gcrd_ptr->type_of_record);

                exit(1);

            }

		}

	}

	return ret_val;

}



struct this_gift_card *thisone;



int main(int argc, char **argv) {

    if (argc != 3) {

        fprintf(stderr, "usage: %s <1|2> file.gft\n", argv[0]);

        fprintf(stderr, "  - Use 1 for text output, 2 for JSON output\n");

        return 1;

    }

	FILE *input_fd = fopen(argv[2],"r");

    if (!input_fd) {

        fprintf(stderr, "error opening file\n");

        return 1;

    }

	thisone = gift_card_reader(input_fd);

	if (argv[1][0] == '1') print_gift_card_info(thisone);

    else if (argv[1][0] == '2') gift_card_json(thisone);



	return 0;

}

Last updated