FreeRDP
TestEncodedTypes.c
1 
20 #include <stdio.h>
21 #include <float.h>
22 #include <limits.h>
23 #include <math.h>
24 
25 #include <winpr/crypto.h>
26 #include <freerdp/utils/encoded_types.h>
27 
28 #define MIN(x, y) ((x) < (y)) ? (x) : (y)
29 #define MAX(x, y) ((x) > (y)) ? (x) : (y)
30 
31 static BOOL test_signed_integer_read_write_equal(INT32 value)
32 {
33  INT32 rvalue = 0;
34  BYTE buffer[32] = { 0 };
35  wStream sbuffer = { 0 };
36  wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
37  WINPR_ASSERT(s);
38 
39  if (!freerdp_write_four_byte_signed_integer(s, value))
40  {
41  (void)fprintf(stderr, "[%s(%" PRId32 ")] failed to write to stream\n", __func__, value);
42  return FALSE;
43  }
44  if (!Stream_SetPosition(s, 0))
45  {
46  (void)fprintf(stderr, "[%s(%" PRId32 ")] failed to reset stream position\n", __func__,
47  value);
48  return FALSE;
49  }
50  if (!freerdp_read_four_byte_signed_integer(s, &rvalue))
51  {
52  (void)fprintf(stderr, "[%s(%" PRId32 ")] failed to read from stream\n", __func__, value);
53  return FALSE;
54  }
55  if (value != rvalue)
56  {
57  (void)fprintf(stderr, "[%s(%" PRId32 ")] read invalid value %" PRId32 " from stream\n",
58  __func__, value, rvalue);
59  return FALSE;
60  }
61  return TRUE;
62 }
63 
64 static BOOL test_signed_integer_write_oor(INT32 value)
65 {
66  BYTE buffer[32] = { 0 };
67  wStream sbuffer = { 0 };
68  wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
69  WINPR_ASSERT(s);
70 
71  if (freerdp_write_four_byte_signed_integer(s, value))
72  {
73  (void)fprintf(stderr,
74  "[%s(%" PRId32 ")] out of range value not detected and written to stream\n",
75  __func__, value);
76  return FALSE;
77  }
78  return TRUE;
79 }
80 
81 static BOOL test_signed_integers(void)
82 {
83  const INT32 outofrange[] = { FREERDP_FOUR_BYTE_SIGNED_INT_MAX + 1,
84  FREERDP_FOUR_BYTE_SIGNED_INT_MIN - 1, INT32_MAX, INT32_MIN };
85  const INT32 limits[] = { 1, 0, -1, FREERDP_FOUR_BYTE_SIGNED_INT_MAX,
86  FREERDP_FOUR_BYTE_SIGNED_INT_MIN };
87 
88  for (size_t x = 0; x < ARRAYSIZE(limits); x++)
89  {
90  if (!test_signed_integer_read_write_equal(limits[x]))
91  return FALSE;
92  }
93  for (size_t x = 0; x < ARRAYSIZE(outofrange); x++)
94  {
95  if (!test_signed_integer_write_oor(outofrange[x]))
96  return FALSE;
97  }
98  for (size_t x = 0; x < 100000; x++)
99  {
100  INT32 val = 0;
101  winpr_RAND(&val, sizeof(val));
102  val = MAX(val, 0);
103  val = MIN(val, FREERDP_FOUR_BYTE_SIGNED_INT_MAX);
104 
105  const INT32 nval = -val;
106  if (!test_signed_integer_read_write_equal(val))
107  return FALSE;
108  if (!test_signed_integer_read_write_equal(nval))
109  return FALSE;
110  }
111  return TRUE;
112 }
113 
114 static BOOL test_float_read_write_equal(double value)
115 {
116  BYTE exp = 0;
117  double rvalue = FP_NAN;
118  BYTE buffer[32] = { 0 };
119  wStream sbuffer = { 0 };
120  wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
121  WINPR_ASSERT(s);
122 
123  if (!freerdp_write_four_byte_float(s, value))
124  {
125  (void)fprintf(stderr, "[%s(%lf)] failed to write to stream\n", __func__, value);
126  return FALSE;
127  }
128  if (!Stream_SetPosition(s, 0))
129  {
130  (void)fprintf(stderr, "[%s(%lf)] failed to reset stream position\n", __func__, value);
131  return FALSE;
132  }
133  if (!freerdp_read_four_byte_float_exp(s, &rvalue, &exp))
134  {
135  (void)fprintf(stderr, "[%s(%lf)] failed to read from stream\n", __func__, value);
136  return FALSE;
137  }
138  const double diff = fabs(value - rvalue);
139  const double expdiff = diff * pow(10, exp);
140  if (expdiff >= 1.0)
141  {
142  (void)fprintf(stderr, "[%s(%lf)] read invalid value %lf from stream\n", __func__, value,
143  rvalue);
144  return FALSE;
145  }
146  return TRUE;
147 }
148 
149 static BOOL test_floag_write_oor(double value)
150 {
151  BYTE buffer[32] = { 0 };
152  wStream sbuffer = { 0 };
153  wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
154  WINPR_ASSERT(s);
155 
156  if (freerdp_write_four_byte_float(s, value))
157  {
158  (void)fprintf(stderr, "[%s(%lf)] out of range value not detected and written to stream\n",
159  __func__, value);
160  return FALSE;
161  }
162  return TRUE;
163 }
164 
165 static double get(void)
166 {
167  double val = NAN;
168  do
169  {
170  winpr_RAND(&val, sizeof(val));
171  } while ((val < 0.0) || (val > FREERDP_FOUR_BYTE_FLOAT_MAX) || isnan(val) || isinf(val));
172  return val;
173 }
174 
175 static BOOL test_floats(void)
176 {
177  const double outofrange[] = { FREERDP_FOUR_BYTE_FLOAT_MAX + 1, FREERDP_FOUR_BYTE_FLOAT_MIN - 1,
178  DBL_MAX, -DBL_MAX };
179  const double limits[] = { 100045.26129238126, 1, 0, -1, FREERDP_FOUR_BYTE_FLOAT_MAX,
180  FREERDP_FOUR_BYTE_FLOAT_MIN };
181 
182  for (size_t x = 0; x < ARRAYSIZE(limits); x++)
183  {
184  if (!test_float_read_write_equal(limits[x]))
185  return FALSE;
186  }
187  for (size_t x = 0; x < ARRAYSIZE(outofrange); x++)
188  {
189  if (!test_floag_write_oor(outofrange[x]))
190  return FALSE;
191  }
192  for (size_t x = 0; x < 100000; x++)
193  {
194  double val = get();
195 
196  const double nval = -val;
197  if (!test_float_read_write_equal(val))
198  return FALSE;
199  if (!test_float_read_write_equal(nval))
200  return FALSE;
201  }
202  return TRUE;
203 }
204 
205 int TestEncodedTypes(int argc, char* argv[])
206 {
207  WINPR_UNUSED(argc);
208  WINPR_UNUSED(argv);
209 
210  if (!test_signed_integers())
211  return -1;
212  if (!test_floats())
213  return -1;
214  return 0;
215 }