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