- convert t/t107bmp.t to Test::More
[imager.git] / limits.c
1 /*
2 =head1 NAME
3
4 limits.c - manages data/functions for limiting the sizes of images read from files.
5
6 =head1 SYNOPSIS
7
8   // user code
9   if (!i_set_image_file_limits(max_width, max_height, max_bytes)) {
10     // error
11   }
12   i_get_image_file_limits(&max_width, &max_height, &max_bytes);
13
14   // file reader implementations
15   if (!i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))) {
16     // error handling
17   }
18
19 =head1 DESCRIPTION
20
21 Manage limits for image files read by Imager.
22
23 Setting a value of zero means that limit will be ignored.
24   
25  */
26
27 #include "imagei.h"
28
29 static int max_width, max_height;
30 static int max_bytes;
31
32 int
33 i_set_image_file_limits(int width, int height, int bytes) {
34   i_clear_error();
35
36   if (width < 0) {
37     i_push_error(0, "width must be non-negative");
38     return 0;
39   }
40   if (height < 0) {
41     i_push_error(0, "height must be non-negative");
42     return 0;
43   }
44   if (bytes < 0) {
45     i_push_error(0, "bytes must be non-negative");
46     return 0;
47   }
48
49   max_width = width;
50   max_height = height;
51   max_bytes = bytes;
52
53   return 1;
54 }
55
56 int
57 i_get_image_file_limits(int *width, int *height, int *bytes) {
58   i_clear_error();
59
60   *width = max_width;
61   *height = max_height;
62   *bytes = max_bytes;
63
64   return 1;
65 }
66
67 int
68 i_int_check_image_file_limits(int width, int height, int channels, int sample_size) {
69   i_clear_error();
70   
71   if (width <= 0) {
72     i_push_errorf(0, "file size limit - image width of %d is not positive",
73                   width);
74     return 0;
75   }
76   if (max_width && width > max_width) {
77     i_push_errorf(0, "file size limit - image width of %d exceeds limit of %d",
78                  width, max_width);
79     return 0;
80   }
81
82   if (height <= 0) {
83     i_push_errorf(0, "file size limit - image height %d is not positive",
84                   height);
85     return 0;
86   }
87
88   if (max_height && height > max_height) {
89     i_push_errorf(0, "file size limit - image height of %d "
90                   "exceeds limit of %d", height, max_height);
91     return 0;
92   }
93
94   if (channels < 1 || channels > MAXCHANNELS) {
95     i_push_errorf(0, "file size limit - channels %d out of range",
96                   channels);
97     return 0;
98   }
99   
100   if (sample_size < 1 || sample_size > sizeof(long double)) {
101     i_push_errorf(0, "file size limit - sample_size %d out of range",
102                   sample_size);
103     return 0;
104   }
105
106   /* This overflow check is a bit more paranoid than usual.
107      We don't protect it under max_bytes since we always want to check 
108      for overflow.
109   */
110   int bytes = width * height * channels * sample_size;
111   if (bytes / width != height * channels * sample_size
112       || bytes / height != width * channels * sample_size) {
113     i_push_error(0, "file size limit - integer overflow calculating storage");
114     return 0;
115   }
116   if (max_bytes) {
117     if (bytes > max_bytes) {
118       i_push_errorf(0, "file size limit - storage size of %d "
119                     "exceeds limit of %d", bytes, max_bytes);
120       return 0;
121     }
122   }
123
124   return 1;
125 }