]> git.imager.perl.org - imager.git/blame - limits.c
0.84_01 development release
[imager.git] / limits.c
CommitLineData
77157728
TC
1/*
2=head1 NAME
3
4limits.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
21Manage limits for image files read by Imager.
22
23Setting a value of zero means that limit will be ignored.
24
25 */
26
92bda632 27#include "imageri.h"
77157728 28
8d14daab
TC
29static i_img_dim max_width, max_height;
30static size_t max_bytes = 0x40000000;
77157728 31
87deb14c
TC
32/*
33=item i_set_image_file_limits(width, height, bytes)
34
35=category Files
36=synopsis i_set_image_file_limits(500, 500, 1000000);
37
38Set limits on the sizes of images read by Imager.
39
40Setting a limit to 0 means that limit is ignored.
41
42Negative limits result in failure.
43
8d14daab
TC
44Parameters:
45
46=over
47
48=item *
49
50i_img_dim width, height - maximum width and height.
51
52=item *
53
54size_t bytes - maximum size in memory in bytes
55
56=back
57
87deb14c
TC
58Returns non-zero on success.
59
60=cut
61*/
62
77157728 63int
8d14daab 64i_set_image_file_limits(i_img_dim width, i_img_dim height, size_t bytes) {
77157728
TC
65 i_clear_error();
66
67 if (width < 0) {
68 i_push_error(0, "width must be non-negative");
69 return 0;
70 }
71 if (height < 0) {
72 i_push_error(0, "height must be non-negative");
73 return 0;
74 }
75 if (bytes < 0) {
76 i_push_error(0, "bytes must be non-negative");
77 return 0;
78 }
79
80 max_width = width;
81 max_height = height;
82 max_bytes = bytes;
83
84 return 1;
85}
86
87deb14c
TC
87/*
88=item i_get_image_file_limits(&width, &height, &bytes)
89
90=category Files
91=synopsis i_get_image_file_limits(&width, &height, &bytes)
92
93Retrieves the file limits set by i_set_image_file_limits().
94
8d14daab
TC
95=over
96
97=item *
98
99i_img_dim *width, *height - the maximum width and height of the image.
100
101=item *
102
103size_t *bytes - size in memory of the image in bytes.
104
105=back
106
87deb14c
TC
107=cut
108*/
109
77157728 110int
8d14daab 111i_get_image_file_limits(i_img_dim *width, i_img_dim *height, size_t *bytes) {
77157728
TC
112 i_clear_error();
113
114 *width = max_width;
115 *height = max_height;
116 *bytes = max_bytes;
117
118 return 1;
119}
120
87deb14c
TC
121/*
122=item i_int_check_image_file_limits(width, height, channels, sample_size)
123
124=category Files
125=synopsis i_i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
126
127Checks the size of a file in memory against the configured image file
128limits.
129
130This also range checks the values to those permitted by Imager and
131checks for overflows in calculating the size.
132
133Returns non-zero if the file is within limits.
134
135This function is intended to be called by image file read functions.
136
137=cut
138*/
139
77157728 140int
8d14daab
TC
141i_int_check_image_file_limits(i_img_dim width, i_img_dim height, int channels, size_t sample_size) {
142 size_t bytes;
77157728
TC
143 i_clear_error();
144
145 if (width <= 0) {
8d14daab
TC
146 i_push_errorf(0, "file size limit - image width of %" i_DF " is not positive",
147 i_DFc(width));
77157728
TC
148 return 0;
149 }
150 if (max_width && width > max_width) {
8d14daab
TC
151 i_push_errorf(0, "file size limit - image width of %" i_DF " exceeds limit of %" i_DF,
152 i_DFc(width), i_DFc(max_width));
77157728
TC
153 return 0;
154 }
155
156 if (height <= 0) {
8d14daab
TC
157 i_push_errorf(0, "file size limit - image height %" i_DF " is not positive",
158 i_DFc(height));
77157728
TC
159 return 0;
160 }
161
162 if (max_height && height > max_height) {
8d14daab
TC
163 i_push_errorf(0, "file size limit - image height of %" i_DF
164 " exceeds limit of %" i_DF, i_DFc(height), i_DFc(max_height));
77157728
TC
165 return 0;
166 }
167
168 if (channels < 1 || channels > MAXCHANNELS) {
169 i_push_errorf(0, "file size limit - channels %d out of range",
170 channels);
171 return 0;
172 }
173
174 if (sample_size < 1 || sample_size > sizeof(long double)) {
8d14daab
TC
175 i_push_errorf(0, "file size limit - sample_size %ld out of range",
176 (long)sample_size);
77157728
TC
177 return 0;
178 }
179
180 /* This overflow check is a bit more paranoid than usual.
181 We don't protect it under max_bytes since we always want to check
182 for overflow.
183 */
5caa40a6 184 bytes = width * height * channels * sample_size;
77157728
TC
185 if (bytes / width != height * channels * sample_size
186 || bytes / height != width * channels * sample_size) {
187 i_push_error(0, "file size limit - integer overflow calculating storage");
188 return 0;
189 }
190 if (max_bytes) {
191 if (bytes > max_bytes) {
8d14daab
TC
192 i_push_errorf(0, "file size limit - storage size of %lu "
193 "exceeds limit of %lu", (unsigned long)bytes,
194 (unsigned long)max_bytes);
77157728
TC
195 return 0;
196 }
197 }
198
199 return 1;
200}