0.84 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
TC
28
29static int max_width, max_height;
30static int max_bytes;
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
44Returns non-zero on success.
45
46=cut
47*/
48
77157728
TC
49int
50i_set_image_file_limits(int width, int height, int bytes) {
51 i_clear_error();
52
53 if (width < 0) {
54 i_push_error(0, "width must be non-negative");
55 return 0;
56 }
57 if (height < 0) {
58 i_push_error(0, "height must be non-negative");
59 return 0;
60 }
61 if (bytes < 0) {
62 i_push_error(0, "bytes must be non-negative");
63 return 0;
64 }
65
66 max_width = width;
67 max_height = height;
68 max_bytes = bytes;
69
70 return 1;
71}
72
87deb14c
TC
73/*
74=item i_get_image_file_limits(&width, &height, &bytes)
75
76=category Files
77=synopsis i_get_image_file_limits(&width, &height, &bytes)
78
79Retrieves the file limits set by i_set_image_file_limits().
80
81=cut
82*/
83
77157728
TC
84int
85i_get_image_file_limits(int *width, int *height, int *bytes) {
86 i_clear_error();
87
88 *width = max_width;
89 *height = max_height;
90 *bytes = max_bytes;
91
92 return 1;
93}
94
87deb14c
TC
95/*
96=item i_int_check_image_file_limits(width, height, channels, sample_size)
97
98=category Files
99=synopsis i_i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
100
101Checks the size of a file in memory against the configured image file
102limits.
103
104This also range checks the values to those permitted by Imager and
105checks for overflows in calculating the size.
106
107Returns non-zero if the file is within limits.
108
109This function is intended to be called by image file read functions.
110
111=cut
112*/
113
77157728
TC
114int
115i_int_check_image_file_limits(int width, int height, int channels, int sample_size) {
5caa40a6 116 int bytes;
77157728
TC
117 i_clear_error();
118
119 if (width <= 0) {
120 i_push_errorf(0, "file size limit - image width of %d is not positive",
121 width);
122 return 0;
123 }
124 if (max_width && width > max_width) {
125 i_push_errorf(0, "file size limit - image width of %d exceeds limit of %d",
126 width, max_width);
127 return 0;
128 }
129
130 if (height <= 0) {
131 i_push_errorf(0, "file size limit - image height %d is not positive",
132 height);
133 return 0;
134 }
135
136 if (max_height && height > max_height) {
137 i_push_errorf(0, "file size limit - image height of %d "
138 "exceeds limit of %d", height, max_height);
139 return 0;
140 }
141
142 if (channels < 1 || channels > MAXCHANNELS) {
143 i_push_errorf(0, "file size limit - channels %d out of range",
144 channels);
145 return 0;
146 }
147
148 if (sample_size < 1 || sample_size > sizeof(long double)) {
149 i_push_errorf(0, "file size limit - sample_size %d out of range",
150 sample_size);
151 return 0;
152 }
153
154 /* This overflow check is a bit more paranoid than usual.
155 We don't protect it under max_bytes since we always want to check
156 for overflow.
157 */
5caa40a6 158 bytes = width * height * channels * sample_size;
77157728
TC
159 if (bytes / width != height * channels * sample_size
160 || bytes / height != width * channels * sample_size) {
161 i_push_error(0, "file size limit - integer overflow calculating storage");
162 return 0;
163 }
164 if (max_bytes) {
165 if (bytes > max_bytes) {
166 i_push_errorf(0, "file size limit - storage size of %d "
167 "exceeds limit of %d", bytes, max_bytes);
168 return 0;
169 }
170 }
171
172 return 1;
173}