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