LCOV - code coverage report
Current view: top level - homework-1-kiettnguyen - giftcardreader.c (source / functions) Hit Total Coverage
Test: giftcardreader.info Lines: 72 190 37.9 %
Date: 2022-02-18 19:11:14 Functions: 4 6 66.7 %

          Line data    Source code
       1             : /*
       2             :  * Gift Card Reading Application
       3             :  * Original Author: Shoddycorp's Cut-Rate Contracting
       4             :  * Comments added by: Justin Cappos (JAC) and Brendan Dolan-Gavitt (BDG)
       5             :  * Maintainer:
       6             :  * Date: 8 July 2020
       7             :  */
       8             : 
       9             : 
      10             : #include "giftcard.h"
      11             : 
      12             : #include <stdio.h>
      13             : #include <strings.h>
      14             : #include <limits.h>
      15             : // .,~==== interpreter for THX-1138 assembly ====~,.
      16             : //
      17             : // This is an emulated version of a microcontroller with
      18             : // 16 registers, one flag (the zero flag), and display
      19             : // functionality. Programs can operate on the message
      20             : // buffer and use opcode 0x07 to update the display, so
      21             : // that animated greetings can be created.
      22             : 
      23           0 : void animate(char *msg, unsigned char *program) {
      24             :     unsigned char regs[16];
      25           0 :     char *mptr = msg; // TODO: how big is this buffer?
      26           0 :     unsigned char *pc = program;
      27           0 :     int i = 0;
      28           0 :         int zf = 0;
      29           0 :     int count =0;
      30           0 :     int count2 =0;
      31           0 :     unsigned char lastpc =0;
      32           0 :     while (pc< program+256) {
      33             :         unsigned char op, arg1, arg2;
      34           0 :         op = *pc;
      35           0 :         arg1 = *(pc+1);
      36           0 :         arg2 = *(pc+2);
      37           0 :         switch (*pc) {
      38             :             case 0x00:
      39           0 :                 break;
      40             :             case 0x01:
      41           0 :                 regs[arg1] = *mptr;
      42           0 :                 break;
      43             :             case 0x02:
      44           0 :                 if(arg1<0 || arg1>15){
      45           0 :                         exit(0);
      46             :                 }       
      47           0 :                 *mptr = regs[arg1]; //crash here
      48           0 :                 break;
      49             :             case 0x03:
      50           0 :                 mptr += (char)arg1;
      51           0 :                 break;
      52             :             case 0x04:
      53           0 :                 regs[arg2] = arg1;
      54           0 :                 break;
      55             :             case 0x05:
      56           0 :                 regs[arg1] ^= regs[arg2];
      57           0 :                 zf = !regs[arg1];
      58           0 :                 break;
      59             :             case 0x06:
      60           0 :                 regs[arg1] += regs[arg2];
      61           0 :                 zf = !regs[arg1];
      62           0 :                 break;
      63             :             case 0x07:
      64           0 :                 puts(msg);
      65           0 :                 break;
      66             :             case 0x08:
      67           0 :                 goto done;
      68             :             case 0x09:
      69           0 :                 if(pc< program+256+ (unsigned char)arg1){
      70           0 :                 pc += (unsigned char)arg1;
      71           0 :                 }
      72             :                 else{
      73           0 :                         goto done;
      74             :                 }
      75           0 :                 break;
      76             :             case 0x10:
      77           0 :                 if(pc< program+256+ (unsigned char)arg1){
      78           0 :                         if (zf) pc += (unsigned char)arg1;
      79           0 :                 }
      80             :                 else{
      81           0 :                         goto done;
      82             :                 }
      83           0 :                 break;
      84             :         }
      85           0 :         pc+=3;
      86           0 :         count2++;
      87           0 :         if (count2 > 80)
      88             :         {
      89           0 :                 goto done;
      90             :         }       
      91             :         
      92             :     }
      93             : done:
      94           0 :     pc =0;
      95           0 :     return;
      96             : }
      97             : 
      98           1 : int get_gift_card_value(struct this_gift_card *thisone) {
      99             :         struct gift_card_data *gcd_ptr;
     100             :         struct gift_card_record_data *gcrd_ptr;
     101             :         struct gift_card_amount_change *gcac_ptr;
     102           1 :         int ret_count = 0;
     103             : 
     104           1 :         gcd_ptr = thisone->gift_card_data;
     105           2 :         for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
     106           1 :                 gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
     107           1 :                 if (gcrd_ptr->type_of_record == 1) {
     108           1 :                         gcac_ptr = gcrd_ptr->actual_record;
     109           1 :                         ret_count += gcac_ptr->amount_added;
     110           1 :                 }       
     111           1 :         }
     112           1 :         return ret_count;
     113             : }
     114             : 
     115           1 : void print_gift_card_info(struct this_gift_card *thisone) {
     116             :         struct gift_card_data *gcd_ptr;
     117             :         struct gift_card_record_data *gcrd_ptr;
     118             :         struct gift_card_amount_change *gcac_ptr;
     119             :     struct gift_card_program *gcp_ptr;
     120             : 
     121           1 :         gcd_ptr = thisone->gift_card_data;
     122           1 :         printf("   Merchant ID: %32.32s\n",gcd_ptr->merchant_id);
     123           1 :         printf("   Customer ID: %32.32s\n",gcd_ptr->customer_id);
     124           1 :         printf("   Num records: %d\n",gcd_ptr->number_of_gift_card_records);
     125           2 :         for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
     126           1 :                 gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
     127           1 :                 if (gcrd_ptr->type_of_record == 1) {
     128           1 :                         printf("      record_type: amount_change\n");
     129           1 :                         gcac_ptr = gcrd_ptr->actual_record;
     130           1 :                         printf("      amount_added: %d\n",gcac_ptr->amount_added);
     131           1 :                         if (gcac_ptr->amount_added>0) {
     132           1 :                                 printf("      signature: %32.32s\n",gcac_ptr->actual_signature);
     133           1 :                         }
     134           1 :                 }       
     135           0 :                 else if (gcrd_ptr->type_of_record == 2) {
     136           0 :                         printf("      record_type: message\n");
     137           0 :                         printf("      message: %s\n",(char *)gcrd_ptr->actual_record);
     138           0 :                 }
     139           0 :                 else if (gcrd_ptr->type_of_record == 3) {
     140           0 :             gcp_ptr = gcrd_ptr->actual_record;
     141           0 :                         printf("      record_type: animated message\n");
     142             :             // BDG: Hmm... is message guaranteed to be null-terminated?
     143           0 :             printf("      message: %s\n", gcp_ptr->message);
     144           0 :             printf("  [running embedded program]  \n");
     145           0 :             animate(gcp_ptr->message, gcp_ptr->program);
     146           0 :                 }
     147           1 :         }
     148           1 :         printf("  Total value: %d\n\n",get_gift_card_value(thisone));
     149           1 : }
     150             : 
     151             : // Added to support web functionalities
     152           0 : void gift_card_json(struct this_gift_card *thisone) {
     153             :     struct gift_card_data *gcd_ptr;
     154             :     struct gift_card_record_data *gcrd_ptr;
     155             :     struct gift_card_amount_change *gcac_ptr;
     156           0 :     gcd_ptr = thisone->gift_card_data;
     157           0 :     printf("{\n");
     158           0 :     printf("  \"merchant_id\": \"%32.32s\",\n", gcd_ptr->merchant_id);
     159           0 :     printf("  \"customer_id\": \"%32.32s\",\n", gcd_ptr->customer_id);
     160           0 :     printf("  \"total_value\": %d,\n", get_gift_card_value(thisone));
     161           0 :     printf("  \"records\": [\n");
     162           0 :         for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
     163           0 :         gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
     164           0 :         printf("    {\n");
     165           0 :         if (gcrd_ptr->type_of_record == 1) {
     166           0 :             printf("      \"record_type\": \"amount_change\",\n");
     167           0 :             gcac_ptr = gcrd_ptr->actual_record;
     168           0 :             printf("      \"amount_added\": %d,\n",gcac_ptr->amount_added);
     169           0 :             if (gcac_ptr->amount_added>0) {
     170             :                // printf("      \"signature\": \"%32.32s\"\n",gcac_ptr->actual_signature);
     171           0 :             }
     172           0 :         }
     173           0 :         else if (gcrd_ptr->type_of_record == 2) {
     174           0 :                         printf("      \"record_type\": \"message\",\n");
     175           0 :                         printf("      \"message\": \"%s\"\n",(char *)gcrd_ptr->actual_record);
     176           0 :         }
     177           0 :         else if (gcrd_ptr->type_of_record == 3) {
     178           0 :             struct gift_card_program *gcp = gcrd_ptr->actual_record;
     179           0 :                         printf("      \"record_type\": \"animated message\",\n");
     180           0 :                         printf("      \"message\": \"%s\",\n",gcp->message);
     181             :             // programs are binary so we will hex for the json
     182           0 :             char *hexchars = "01234567890abcdef";
     183             :             char program_hex[512+1];
     184           0 :             program_hex[512] = '\0';
     185             :             int i;
     186           0 :             for(i = 0; i < 256; i++) {
     187           0 :                 program_hex[i*2] = hexchars[((gcp->program[i] & 0xf0) >> 4)];
     188           0 :                 program_hex[i*2+1] = hexchars[(gcp->program[i] & 0x0f)];
     189           0 :             }
     190           0 :                         printf("      \"program\": \"%s\"\n",program_hex);
     191           0 :         }
     192           0 :         if (i < gcd_ptr->number_of_gift_card_records-1)
     193           0 :             printf("    },\n");
     194             :         else
     195           0 :             printf("    }\n");
     196           0 :     }
     197           0 :     printf("  ]\n");
     198           0 :     printf("}\n");
     199           0 : }
     200             : 
     201             : 
     202           1 : struct this_gift_card *gift_card_reader(FILE *input_fd) {
     203             : 
     204           1 :         struct this_gift_card *ret_val = malloc(sizeof(struct this_gift_card));
     205             :     void *optr;
     206             :         void *ptr;
     207             : 
     208             :         // Loop to do the whole file
     209           2 :         while (!feof(input_fd)) {
     210             : 
     211             :                 struct gift_card_data *gcd_ptr;
     212             :                 /* JAC: Why aren't return types checked? */
     213           1 :                 fread(&ret_val->num_bytes, 4,1, input_fd);
     214           1 :                 if ( ret_val->num_bytes < 0 || ret_val->num_bytes > 1024*1024*10)
     215             :                 {
     216           0 :                          exit(0);
     217             :                  }
     218             :                 
     219             : 
     220             :                 // Make something the size of the rest and read it in
     221           1 :                 ptr = malloc(ret_val->num_bytes);
     222           1 :                 fread(ptr, ret_val->num_bytes, 1, input_fd);
     223             : 
     224           1 :         optr = ptr-4;
     225             : 
     226           1 :                 gcd_ptr = ret_val->gift_card_data = malloc(sizeof(struct gift_card_data));
     227           1 :                 gcd_ptr->merchant_id = ptr;
     228           1 :                 ptr += 32;      
     229             : //              printf("VD: %d\n",(int)ptr - (int) gcd_ptr->merchant_id);
     230           1 :                 gcd_ptr->customer_id = ptr;
     231           1 :                 ptr += 32;      
     232             :                 /* JAC: Something seems off here... */
     233           1 :                 gcd_ptr->number_of_gift_card_records = *((char *)ptr);
     234           1 :                 ptr += 4;
     235             :                 
     236           1 :                 gcd_ptr->gift_card_record_data = (void *)malloc(gcd_ptr->number_of_gift_card_records*sizeof(void*));
     237             : 
     238             :                 // Now ptr points at the gift card recrod data
     239           2 :                 for (int i=0; i < gcd_ptr->number_of_gift_card_records; i++){
     240             :                 //      printf("i: %d\n",i);
     241             :                         struct gift_card_record_data *gcrd_ptr;
     242           1 :                         gcrd_ptr = gcd_ptr->gift_card_record_data[i] = malloc(sizeof(struct gift_card_record_data));
     243             :                         struct gift_card_amount_change *gcac_ptr;
     244           1 :                         gcac_ptr = gcrd_ptr->actual_record = malloc(sizeof(struct gift_card_record_data));
     245             :             struct gift_card_program *gcp_ptr;
     246           1 :                         gcp_ptr = malloc(sizeof(struct gift_card_program));
     247             : 
     248           1 :                         gcrd_ptr->record_size_in_bytes = *((char *)ptr);
     249             :             //printf("rec at %x, %d bytes\n", ptr - optr, gcrd_ptr->record_size_in_bytes); 
     250           1 :                         ptr += 4;       
     251             :                         //printf("record_data: %d\n",gcrd_ptr->record_size_in_bytes);
     252           1 :                         gcrd_ptr->type_of_record = *((char *)ptr);
     253           1 :                         ptr += 4;       
     254             :             //printf("type of rec: %d\n", gcrd_ptr->type_of_record);
     255             : 
     256             :                         // amount change
     257           1 :                         if (gcrd_ptr->type_of_record == 1) {
     258           1 :                                 gcac_ptr->amount_added = *((int*) ptr);
     259           1 :                                 ptr += 4;       
     260             : 
     261             :                                 // don't need a sig if negative
     262             :                                 /* JAC: something seems off here */
     263           1 :                                 if (gcac_ptr < 0) break;
     264             : 
     265           1 :                                 gcac_ptr->actual_signature = ptr;
     266           1 :                                 ptr+=32;
     267           1 :                         }
     268             :                         // message
     269           1 :                         if (gcrd_ptr->type_of_record == 2) {
     270           0 :                                 gcrd_ptr->actual_record = ptr;
     271             :                         //      printf("ptr: %d\n",ptr);
     272             : 
     273             :                                 // advance by the string size + 1 for nul
     274             :                 // BDG: does not seem right
     275           0 :                                 ptr=ptr+strlen((char *)gcrd_ptr->actual_record)+1;
     276             :                         //      printf("ptr: %d\n",ptr);
     277             : 
     278           0 :                         }
     279             :             // BDG: gift cards can run code?? Might want to check this one carefully...
     280             :             // text animatino (BETA)
     281           1 :             if (gcrd_ptr->type_of_record == 3) {
     282           0 :                 gcp_ptr->message = malloc(32);
     283           0 :                 gcp_ptr->program = malloc(256);
     284           0 :                 memcpy(gcp_ptr->message, ptr, 32);
     285           0 :                 ptr+=32;
     286           0 :                 memcpy(gcp_ptr->program, ptr, 256);
     287           0 :                 ptr+=256;
     288           0 :                 gcrd_ptr->actual_record = gcp_ptr;
     289           0 :             }
     290           1 :                 }
     291             :         }
     292           1 :         return ret_val;
     293             : }
     294             : 
     295             : struct this_gift_card *thisone;
     296             : 
     297           1 : int main(int argc, char **argv) {
     298           1 :     if (argc != 3) {
     299           0 :         fprintf(stderr, "usage: %s <1|2> file.gft\n", argv[0]);
     300           0 :         fprintf(stderr, "  - Use 1 for text output, 2 for JSON output\n");
     301           0 :         return 1;
     302             :     }
     303           1 :         FILE *input_fd = fopen(argv[2],"r");
     304           1 :     if (!input_fd) {
     305           0 :         fprintf(stderr, "error opening file\n");
     306           0 :         return 1;
     307             :     }
     308           1 :         thisone = gift_card_reader(input_fd);
     309           1 :         if (argv[1][0] == '1') print_gift_card_info(thisone);
     310           0 :     else if (argv[1][0] == '2') gift_card_json(thisone);
     311             : 
     312           1 :         return 0;
     313           1 : }

Generated by: LCOV version 1.15