1 /* Test of message digests.
2    Copyright (C) 2018-2021 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16 
17 static void
test_digest_on_files(int (* streamfunc)(FILE *,void *),const char * streamfunc_name,size_t digest_size,const void * expected_for_empty_file,const void * expected_for_small_file,const void * expected_for_large_file)18 test_digest_on_files (int (*streamfunc) (FILE *, void *),
19                       const char *streamfunc_name,
20                       size_t digest_size,
21                       const void *expected_for_empty_file,
22                       const void *expected_for_small_file,
23                       const void *expected_for_large_file)
24 {
25   int pass;
26   unlink (TESTFILE);
27 
28   for (pass = 0; pass < 5; pass++)
29     {
30       {
31         FILE *fp = fopen (TESTFILE, "wb");
32         if (fp == NULL)
33           {
34             fprintf (stderr, "Could not create file %s.\n", TESTFILE);
35             exit (1);
36           }
37         switch (pass)
38           {
39           case 0:
40             /* Nothing to do for the empty file.  */
41             break;
42           case 2:
43             /* Fill the small file, with some header that will be skipped.  */
44             fputs ("ABCD", fp);
45             FALLTHROUGH;
46           case 1:
47             /* Fill the small file.  */
48             fputs ("The quick brown fox jumps over the lazy dog.\n", fp);
49             break;
50           case 4:
51             /* Fill the large file, with some header that will be skipped.  */
52             fputs ("ABCD", fp);
53             FALLTHROUGH;
54           case 3:
55             /* Fill the large file (8 MiB).  */
56             {
57               unsigned int i;
58               for (i = 0; i < 0x400000; i++)
59                 {
60                   unsigned char c[2];
61                   unsigned int j = i * (i-1) * (i-5);
62                   c[0] = (unsigned char)(j >> 6);
63                   c[1] = (i % 499) + (i % 101);
64                   fwrite (c, 1, 2, fp);
65                 }
66             }
67             break;
68           }
69         if (ferror (fp))
70           {
71             fprintf (stderr, "Could not write data to file %s.\n", TESTFILE);
72             exit (1);
73           }
74         fclose (fp);
75       }
76       {
77         /* Test an unaligned digest.  */
78         char *digest = (char *) malloc (digest_size + 1) + 1;
79         const void *expected;
80         FILE *fp;
81         int ret;
82 
83         switch (pass)
84           {
85           case 0:         expected = expected_for_empty_file; break;
86           case 1: case 2: expected = expected_for_small_file; break;
87           case 3: case 4: expected = expected_for_large_file; break;
88           default: abort ();
89           }
90 
91         fp = fopen (TESTFILE, "rb");
92         if (fp == NULL)
93           {
94             fprintf (stderr, "Could not open file %s.\n", TESTFILE);
95             exit (1);
96           }
97         switch (pass)
98           {
99           case 2:
100           case 4:
101             {
102               char header[4];
103               if (fread (header, 1, sizeof (header), fp) != sizeof (header))
104                 {
105                   fprintf (stderr, "Could not read the header of %s.\n",
106                            TESTFILE);
107                   exit (1);
108                 }
109             }
110             break;
111           }
112         ret = streamfunc (fp, digest);
113         if (ret)
114           {
115             fprintf (stderr, "%s failed with error %d\n", streamfunc_name, -ret);
116             exit (1);
117           }
118         if (memcmp (digest, expected, digest_size) != 0)
119           {
120             size_t i;
121             fprintf (stderr, "%s produced wrong result.\n", streamfunc_name);
122             fprintf (stderr, "Expected: ");
123             for (i = 0; i < digest_size; i++)
124               fprintf (stderr, "\\x%02x", ((const unsigned char *) expected)[i]);
125             fprintf (stderr, "\n");
126             fprintf (stderr, "Got:      ");
127             for (i = 0; i < digest_size; i++)
128               fprintf (stderr, "\\x%02x", ((const unsigned char *) digest)[i]);
129             fprintf (stderr, "\n");
130             exit (1);
131           }
132         /* Verify that fp is now positioned at end of file.  */
133         if (getc (fp) != EOF)
134           {
135             fprintf (stderr, "%s left the stream not at EOF\n", streamfunc_name);
136             exit (1);
137           }
138         fclose (fp);
139         free (digest - 1);
140       }
141     }
142 
143   unlink (TESTFILE);
144 }
145