LCOV - code coverage report
Current view: top level - fuzz - fuzz_xfer.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 66 74 89.2 %
Date: 2023-06-12 11:14:12 Functions: 5 5 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 17 30 56.7 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2019, Red Hat, Inc.
       2                 :            :  *
       3                 :            :  * Authors:  Jakub Jelen <jjelen@redhat.com>
       4                 :            :  *
       5                 :            :  * This code is licensed under the GNU LGPL, version 2.1 or later.
       6                 :            :  * See the COPYING file in the top-level directory.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <stdlib.h>
      10                 :            : #include <libcacard.h>
      11                 :            : 
      12                 :            : #include "fuzzer.h"
      13                 :            : 
      14                 :            : #define ARGS "db=\"sql:%s\" use_hw=no soft=(,Test,CAC,,cert1,cert2,cert3)"
      15                 :            : #define APDUBufSize 270
      16                 :            : 
      17                 :            : static GMainLoop *loop;
      18                 :            : static GThread *thread;
      19                 :            : static guint nreaders;
      20                 :            : static GMutex mutex;
      21                 :            : static GCond cond;
      22                 :            : 
      23                 :            : static gpointer
      24                 :          1 : events_thread(gpointer arg)
      25                 :            : {
      26                 :            :     unsigned int reader_id;
      27                 :            :     VEvent *event;
      28                 :            : 
      29                 :            :     (void)arg;
      30                 :            : 
      31                 :            :     while (1) {
      32                 :          4 :         event = vevent_wait_next_vevent();
      33         [ +  + ]:          4 :         if (event->type == VEVENT_LAST) {
      34                 :          1 :             vevent_delete(event);
      35                 :            :             break;
      36                 :            :         }
      37                 :          3 :         reader_id = vreader_get_id(event->reader);
      38         [ +  + ]:          3 :         if (reader_id == VSCARD_UNDEFINED_READER_ID) {
      39                 :          1 :             g_mutex_lock(&mutex);
      40                 :          1 :             vreader_set_id(event->reader, nreaders++);
      41                 :          1 :             g_cond_signal(&cond);
      42                 :          1 :             g_mutex_unlock(&mutex);
      43                 :          1 :             reader_id = vreader_get_id(event->reader);
      44                 :            :         }
      45         [ -  + ]:          3 :         switch (event->type) {
      46                 :            :         case VEVENT_READER_INSERT:
      47                 :            :         case VEVENT_READER_REMOVE:
      48                 :            :         case VEVENT_CARD_INSERT:
      49                 :            :         case VEVENT_CARD_REMOVE:
      50                 :            :             break;
      51                 :          0 :         case VEVENT_LAST:
      52                 :            :         default:
      53                 :          0 :             g_warn_if_reached();
      54                 :          0 :             break;
      55                 :            :         }
      56                 :          3 :         vevent_delete(event);
      57                 :            :     }
      58                 :            : 
      59                 :          1 :     return NULL;
      60                 :            : }
      61                 :            : 
      62                 :          1 : static void libcacard_init(void)
      63                 :            : {
      64                 :            :     VCardEmulOptions *command_line_options = NULL;
      65                 :            :     gchar *dbdir = NULL;
      66                 :            :     gchar *args = NULL;
      67                 :            :     VReader *r;
      68                 :            :     VCardEmulError ret;
      69                 :            : 
      70                 :            :     /* This will use the test directory when running as test and
      71                 :            :      * and dirname part of argv[0] when running from oss-fuzz */
      72                 :          1 :     dbdir = g_test_build_filename(G_TEST_DIST, "db", NULL);
      73                 :          1 :     args = g_strdup_printf(ARGS, dbdir);
      74                 :            : 
      75                 :          1 :     thread = g_thread_new("fuzz/events", events_thread, NULL);
      76                 :            : 
      77                 :          1 :     command_line_options = vcard_emul_options(args);
      78                 :          1 :     ret = vcard_emul_init(command_line_options);
      79         [ -  + ]:          1 :     g_assert_cmpint(ret, ==, VCARD_EMUL_OK);
      80                 :            : 
      81                 :          1 :     r = vreader_get_reader_by_name("Test");
      82   [ -  +  -  + ]:          1 :     g_assert_nonnull(r);
      83                 :          1 :     vreader_free(r); /* get by name ref */
      84                 :            : 
      85                 :          1 :     g_mutex_lock(&mutex);
      86         [ -  + ]:          1 :     while (nreaders == 0)
      87                 :          0 :         g_cond_wait(&cond, &mutex);
      88                 :          1 :     g_mutex_unlock(&mutex);
      89                 :            : 
      90                 :          1 :     g_free(args);
      91                 :          1 :     g_free(dbdir);
      92                 :          1 : }
      93                 :            : 
      94                 :          1 : static void libcacard_finalize(void)
      95                 :            : {
      96                 :          1 :     VReader *reader = vreader_get_reader_by_id(0);
      97                 :            : 
      98                 :            :     /* This actually still generates events ?? */
      99         [ +  - ]:          1 :     if (reader) /*if /remove didn't run */
     100                 :          1 :         vreader_remove_reader(reader);
     101                 :            : 
     102                 :            :     /* This probably supposed to be a event that terminates the loop */
     103                 :          1 :     vevent_queue_vevent(vevent_new(VEVENT_LAST, reader, NULL));
     104                 :            : 
     105                 :            :     /* join */
     106                 :          1 :     g_thread_join(thread);
     107                 :            : 
     108                 :          1 :     vreader_free(reader);
     109                 :            : 
     110                 :          1 :     vcard_emul_finalize();
     111                 :          1 : }
     112                 :            : 
     113                 :          1 : int LLVMFuzzerInitialize(int *argc, char ***argv)
     114                 :            : {
     115                 :            :     VReader *reader;
     116                 :            : 
     117                 :            :     (void) argc;
     118                 :            : 
     119                 :          1 :     g_test_init(argc, argv, NULL);
     120                 :            : 
     121                 :          1 :     loop = g_main_loop_new(NULL, TRUE);
     122                 :            : 
     123                 :          1 :     g_debug("Initializing ...");
     124                 :          1 :     libcacard_init();
     125                 :            : 
     126                 :          1 :     reader = vreader_get_reader_by_id(0);
     127         [ -  + ]:          1 :     if (vreader_card_is_present(reader) != VREADER_OK) {
     128                 :          0 :         g_error("Card inserted but not still not present");
     129                 :            :         return -1;
     130                 :            :     }
     131                 :            : 
     132                 :          1 :     atexit(libcacard_finalize);
     133                 :            : 
     134                 :          1 :     vreader_free(reader);
     135                 :            :     return 0;
     136                 :            : }
     137                 :            : 
     138                 :            : /* We require at least 2b for length and 4 bytes for simplest APDU (Case 1) */
     139                 :            : size_t kMinInputLength = 6;
     140                 :            : 
     141                 :          1 : int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
     142                 :            : {
     143                 :            :     size_t left = Size;
     144                 :            :     uint8_t *data = (uint8_t *) Data;
     145                 :            :     VReader *reader = NULL;
     146                 :          1 :     int dwRecvLength = APDUBufSize;
     147                 :            :     uint8_t pbRecvBuffer[APDUBufSize];
     148                 :            : 
     149         [ -  + ]:          1 :     if (left < kMinInputLength) {
     150                 :          0 :         g_debug("Too short input for APDU");
     151                 :          0 :         return 0;
     152                 :            :     }
     153                 :            : 
     154                 :          1 :     reader = vreader_get_reader_by_id(0);
     155   [ -  +  -  + ]:          1 :     g_assert_nonnull(reader);
     156                 :            : 
     157         [ +  + ]:         88 :     while (left > 0) {
     158                 :            :         VReaderStatus status;
     159                 :            :         size_t data_len;
     160                 :            : 
     161                 :            :         /* Interpret the fuzzing data as follows:
     162                 :            :          * 1 byte       length
     163                 :            :          * length bytes data
     164                 :            :          */
     165                 :         87 :         data_len = (size_t) data[0];
     166                 :         87 :         data++;
     167                 :         87 :         left--;
     168                 :         87 :         data_len = data_len > left ? left : data_len;
     169                 :            : 
     170                 :         87 :         g_debug("Transfering %zu bytes", data_len);
     171                 :         87 :         status = vreader_xfr_bytes(reader,
     172                 :            :                                    data, data_len,
     173                 :            :                                    pbRecvBuffer, &dwRecvLength);
     174         [ -  + ]:         87 :         if (status != VREADER_OK) {
     175         [ #  # ]:          0 :             g_debug("Returned %s", status == VREADER_NO_CARD ? "VREADER_NO_CARD" : "VREADER_OUT_OF_MEMORY");
     176                 :            :         }
     177                 :         87 :         data += data_len;
     178                 :         87 :         left -= data_len;
     179                 :            :     }
     180                 :            : 
     181                 :          1 :     g_debug("Cleaning up");
     182                 :          1 :     vreader_free(reader);
     183                 :            : 
     184                 :          1 :     return 0;
     185                 :            : }
     186                 :            : 
     187                 :            : /* vim: set ts=4 sw=4 tw=0 noet expandtab: */

Generated by: LCOV version 1.14