gosu 0.10.7 → 0.10.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  /* ----------------------------------------------------------------------------
2
2
  * This file was automatically generated by SWIG (http://www.swig.org).
3
- * Version 3.0.8
3
+ * Version 3.0.10
4
4
  *
5
5
  * This file is not intended to be easily readable and contains a number of
6
6
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -98,6 +98,11 @@ module Gosu
98
98
  YELLOW = Gosu::ImmutableColor.new(0xff_ffff00)
99
99
  FUCHSIA = Gosu::ImmutableColor.new(0xff_ff00ff)
100
100
  CYAN = Gosu::ImmutableColor.new(0xff_00ffff)
101
+
102
+ alias hash gl
103
+ def eql?(other)
104
+ gl == other.gl
105
+ end
101
106
  end
102
107
  end
103
108
 
@@ -487,6 +487,12 @@ module Gosu
487
487
  ##
488
488
  # Returns the associated texture contents as binary string of packed RGBA values, useful for use with RMagick (Magick::Image.from_blob).
489
489
  #
490
+ # magick_image = Magick::Image.from_blob(image.to_blob) {
491
+ # self.format = "RGBA"
492
+ # self.size = "#{image.width}x#{image.height}"
493
+ # self.depth = 8
494
+ # }.first
495
+ #
490
496
  # @return [String] a binary string of packed RGBA values.
491
497
  def to_blob; end
492
498
 
@@ -1,5 +1,5 @@
1
1
  #include <Gosu/Directories.hpp>
2
- #include <Gosu/WinUtility.hpp>
2
+ #include "WinUtility.hpp"
3
3
  #include <cwchar>
4
4
  #include <stdexcept>
5
5
  #include <shlobj.h>
@@ -19,6 +19,19 @@ namespace
19
19
  }
20
20
  return buf;
21
21
  }
22
+
23
+ std::wstring exeFilename()
24
+ {
25
+ static std::wstring result;
26
+ if (!result.empty())
27
+ return result;
28
+
29
+ wchar_t buffer[MAX_PATH * 2];
30
+ Gosu::Win::check(::GetModuleFileName(0, buffer, MAX_PATH * 2),
31
+ "getting the module filename");
32
+ result = buffer;
33
+ return result;
34
+ }
22
35
  }
23
36
 
24
37
  void Gosu::useResourceDirectory()
@@ -28,12 +41,21 @@ void Gosu::useResourceDirectory()
28
41
 
29
42
  std::wstring Gosu::resourcePrefix()
30
43
  {
31
- return Win::appDirectory();
44
+ static std::wstring result;
45
+ if (result.empty()) {
46
+ result = exeFilename();
47
+ std::wstring::size_type lastDelim = result.find_last_of(L"\\/");
48
+ if (lastDelim != std::wstring::npos)
49
+ result.resize(lastDelim + 1);
50
+ else
51
+ result = L"";
52
+ }
53
+ return result;
32
54
  }
33
55
 
34
56
  std::wstring Gosu::sharedResourcePrefix()
35
57
  {
36
- return Win::appDirectory();
58
+ return resourcePrefix();
37
59
  }
38
60
 
39
61
  std::wstring Gosu::userSettingsPrefix()
@@ -1,6 +1,6 @@
1
1
  #include <Gosu/IO.hpp>
2
2
  #include <Gosu/Utility.hpp>
3
- #include <Gosu/WinUtility.hpp>
3
+ #include "WinUtility.hpp"
4
4
  #include <windows.h>
5
5
 
6
6
  // IMPR: Error checking
@@ -225,10 +225,15 @@ private:
225
225
  SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTY) > +DEAD_ZONE ||
226
226
  SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_RIGHTY) > +DEAD_ZONE;
227
227
 
228
- for (int button = SDL_CONTROLLER_BUTTON_A; button < SDL_CONTROLLER_BUTTON_DPAD_UP; ++button) {
229
- gamepad[gpButton0 - gpRangeBegin + button - SDL_CONTROLLER_BUTTON_A] =
228
+ int button = 0;
229
+ for (button; button < SDL_CONTROLLER_BUTTON_DPAD_UP; ++button) {
230
+ gamepad[gpButton0 + button - gpRangeBegin] =
230
231
  SDL_GameControllerGetButton(gameController, (SDL_GameControllerButton)button);
231
232
  }
233
+ gamepad[gpButton0 + button++ - gpRangeBegin] =
234
+ SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > +DEAD_ZONE;
235
+ gamepad[gpButton0 + button++ - gpRangeBegin] =
236
+ SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > +DEAD_ZONE;
232
237
  }
233
238
 
234
239
  void pollJoystick(SDL_Joystick *joystick, GamepadBuffer& gamepad)
@@ -121,7 +121,8 @@ namespace
121
121
  };
122
122
  if (fontFlags & Gosu::ffUnderline) {
123
123
  NSMutableDictionary *mutableDict = [dict mutableCopy];
124
- mutableDict[NSUnderlineStyleAttributeName] = @(NSUnderlineStyleSingle);
124
+ // Cannot use accessor syntax here without breaking compilation with OS X 10.7/Xcode 4.6.3.
125
+ [mutableDict setObject:@(NSUnderlineStyleSingle) forKey:NSUnderlineStyleAttributeName];
125
126
  dict = [mutableDict copy];
126
127
  }
127
128
  return dict;
@@ -4,7 +4,7 @@
4
4
  #include <Gosu/Bitmap.hpp>
5
5
  #include <Gosu/Text.hpp>
6
6
  #include <Gosu/Utility.hpp>
7
- #include <Gosu/WinUtility.hpp>
7
+ #include "../WinUtility.hpp"
8
8
  #include <cstdlib>
9
9
  #include <cwchar>
10
10
  #include <algorithm>
@@ -56,7 +56,8 @@ string Gosu::narrow(const std::wstring& ws)
56
56
  string Gosu::language()
57
57
  {
58
58
  @autoreleasepool {
59
- NSString *language = [[NSLocale preferredLanguages] firstObject];
60
- return [language UTF8String] ?: "en";
59
+ // Cannot use accessor syntax here without breaking compilation with OS X 10.7/Xcode 4.6.3.
60
+ NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];
61
+ return language.UTF8String ?: "en";
61
62
  }
62
63
  }
@@ -1,5 +1,5 @@
1
1
  #include <Gosu/Utility.hpp>
2
- #include <Gosu/WinUtility.hpp>
2
+ #include "WinUtility.hpp"
3
3
  #include <windows.h>
4
4
  using namespace std;
5
5
 
@@ -1,77 +1,7 @@
1
- #include <Gosu/WinUtility.hpp>
2
1
  #include <Gosu/Utility.hpp>
2
+ #include "WinUtility.hpp"
3
3
  #include <stdexcept>
4
- #include <vector>
5
-
6
- namespace
7
- {
8
- typedef std::vector<std::tr1::function<bool (MSG&)> > Hooks;
9
- Hooks hooks;
10
-
11
- bool handledByHook(MSG& message)
12
- {
13
- for (Hooks::iterator i = hooks.begin(); i != hooks.end(); ++i)
14
- if ((*i)(message))
15
- return true;
16
-
17
- return false;
18
- }
19
- }
20
-
21
- HINSTANCE Gosu::Win::instance()
22
- {
23
- return check(::GetModuleHandle(0), "getting the module handle");
24
- }
25
-
26
- void Gosu::Win::handleMessage()
27
- {
28
- MSG message;
29
- BOOL ret = ::GetMessage(&message, 0, 0, 0);
30
-
31
- switch (ret)
32
- {
33
- case -1:
34
- {
35
- // GetMessage() failed.
36
- throwLastError("trying to get the next message");
37
- }
38
-
39
- case 0:
40
- {
41
- // GetMessage() found a WM_QUIT message.
42
- // IMPR: Is there a better way to respond to this?
43
- break;
44
- }
45
-
46
- default:
47
- {
48
- // Normal behaviour, if the message does not get handled by
49
- // something else.
50
- if (!handledByHook(message))
51
- {
52
- ::TranslateMessage(&message);
53
- ::DispatchMessage(&message);
54
- }
55
- }
56
- }
57
- }
58
-
59
- void Gosu::Win::processMessages()
60
- {
61
- MSG message;
62
-
63
- while (::PeekMessage(&message, 0, 0, 0, PM_REMOVE))
64
- if (!handledByHook(message))
65
- {
66
- ::TranslateMessage(&message);
67
- ::DispatchMessage(&message);
68
- }
69
- }
70
-
71
- void Gosu::Win::registerMessageHook(const std::tr1::function<bool (MSG&)>& hook)
72
- {
73
- hooks.push_back(hook);
74
- }
4
+ #include <windows.h>
75
5
 
76
6
  void Gosu::Win::throwLastError(const std::string& action)
77
7
  {
@@ -107,31 +37,3 @@ void Gosu::Win::throwLastError(const std::string& action)
107
37
  // Now throw it.
108
38
  throw std::runtime_error(message);
109
39
  }
110
-
111
- std::wstring Gosu::Win::appFilename()
112
- {
113
- static std::wstring result;
114
- if (!result.empty())
115
- return result;
116
-
117
- wchar_t buffer[MAX_PATH * 2];
118
- check(::GetModuleFileName(0, buffer, MAX_PATH * 2),
119
- "getting the module filename");
120
- result = buffer;
121
- return result;
122
- }
123
-
124
- std::wstring Gosu::Win::appDirectory()
125
- {
126
- static std::wstring result;
127
- if (!result.empty())
128
- return result;
129
-
130
- result = appFilename();
131
- std::wstring::size_type lastDelim = result.find_last_of(L"\\/");
132
- if (lastDelim != std::wstring::npos)
133
- result.resize(lastDelim + 1);
134
- else
135
- result = L"";
136
- return result;
137
- }
@@ -0,0 +1,30 @@
1
+ #ifndef GOSU_WINUTILITY_HPP
2
+ #define GOSU_WINUTILITY_HPP
3
+
4
+ #include <Gosu/Platform.hpp>
5
+ #include <string>
6
+
7
+ namespace Gosu
8
+ {
9
+ //! Implementation helpers for the Windows platform.
10
+ namespace Win
11
+ {
12
+ //! Throws an exception according to the error which GetLastError()
13
+ //! returns, optionally prefixed with "While (action), the following
14
+ //! error occured: ".
15
+ GOSU_NORETURN void throwLastError(const std::string& action = "");
16
+
17
+ //! Small helper function that throws an exception whenever the value
18
+ //! passed through is false. Note that this doesn't make sense for all
19
+ //! Windows API functions, but for most of them.
20
+ template<typename T>
21
+ inline T check(T valToCheck, const std::string& action = "")
22
+ {
23
+ if (!valToCheck)
24
+ throwLastError(action);
25
+ return valToCheck;
26
+ }
27
+ }
28
+ }
29
+
30
+ #endif
@@ -1,4 +1,4 @@
1
- /* stb_image - v2.12 - public domain image loader - http://nothings.org/stb_image.h
1
+ /* stb_image - v2.12 with fixes from https://github.com/nothings/stb/pull/343 - public domain image loader - http://nothings.org/stb_image.h
2
2
  no warranty implied; use at your own risk
3
3
 
4
4
  Do this:
@@ -566,6 +566,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
566
566
  #include <stddef.h> // ptrdiff_t on osx
567
567
  #include <stdlib.h>
568
568
  #include <string.h>
569
+ #include <limits.h>
569
570
 
570
571
  #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
571
572
  #include <math.h> // ldexp
@@ -900,6 +901,77 @@ static void *stbi__malloc(size_t size)
900
901
  return STBI_MALLOC(size);
901
902
  }
902
903
 
904
+ // stb_image uses ints pervasively, including for offset calculations.
905
+ // therefore the largest decoded image size we can support with the
906
+ // current code, even on 64-bit targets, is INT_MAX. this is not a
907
+ // significant limitation for the intended use case.
908
+ //
909
+ // we do, however, need to make sure our size calculations don't
910
+ // overflow. hence a few helper functions for size calculations that
911
+ // multiply integers together, making sure that they're non-negative
912
+ // and no overflow occurs.
913
+
914
+ // return 1 if the sum is valid, 0 on overflow.
915
+ // negative terms are considered invalid.
916
+ static int stbi__addsizes_valid(int a, int b)
917
+ {
918
+ if (b < 0) return 0;
919
+ // now 0 <= b <= INT_MAX, hence also
920
+ // 0 <= INT_MAX - b <= INTMAX.
921
+ // And "a + b <= INT_MAX" (which might overflow) is the
922
+ // same as a <= INT_MAX - b (no overflow)
923
+ return a <= INT_MAX - b;
924
+ }
925
+
926
+ // returns 1 if the product is valid, 0 on overflow.
927
+ // negative factors are considered invalid.
928
+ static int stbi__mul2sizes_valid(int a, int b)
929
+ {
930
+ if (a < 0 || b < 0) return 0;
931
+ if (b == 0) return 1; // mul-by-0 is always safe
932
+ // portable way to check for no overflows in a*b
933
+ return a <= INT_MAX/b;
934
+ }
935
+
936
+ // returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
937
+ static int stbi__mad2sizes_valid(int a, int b, int add)
938
+ {
939
+ return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
940
+ }
941
+
942
+ // returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
943
+ static int stbi__mad3sizes_valid(int a, int b, int c, int add)
944
+ {
945
+ return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
946
+ stbi__addsizes_valid(a*b*c, add);
947
+ }
948
+
949
+ // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
950
+ static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
951
+ {
952
+ return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
953
+ stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
954
+ }
955
+
956
+ // mallocs with size overflow checking
957
+ static void *stbi__malloc_mad2(int a, int b, int add)
958
+ {
959
+ if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
960
+ return stbi__malloc(a*b + add);
961
+ }
962
+
963
+ static void *stbi__malloc_mad3(int a, int b, int c, int add)
964
+ {
965
+ if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;
966
+ return stbi__malloc(a*b*c + add);
967
+ }
968
+
969
+ static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
970
+ {
971
+ if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
972
+ return stbi__malloc(a*b*c*d + add);
973
+ }
974
+
903
975
  // stbi__err - error
904
976
  // stbi__errpf - error returning pointer to float
905
977
  // stbi__errpuc - error returning pointer to unsigned char
@@ -1346,7 +1418,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
1346
1418
  if (req_comp == img_n) return data;
1347
1419
  STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
1348
1420
 
1349
- good = (unsigned char *) stbi__malloc(req_comp * x * y);
1421
+ good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
1350
1422
  if (good == NULL) {
1351
1423
  STBI_FREE(data);
1352
1424
  return stbi__errpuc("outofmem", "Out of memory");
@@ -1386,7 +1458,9 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
1386
1458
  static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
1387
1459
  {
1388
1460
  int i,k,n;
1389
- float *output = (float *) stbi__malloc(x * y * comp * sizeof(float));
1461
+ float *output;
1462
+ if (!data) return NULL;
1463
+ output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
1390
1464
  if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }
1391
1465
  // compute number of non-alpha components
1392
1466
  if (comp & 1) n = comp; else n = comp-1;
@@ -1406,7 +1480,9 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
1406
1480
  static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp)
1407
1481
  {
1408
1482
  int i,k,n;
1409
- stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp);
1483
+ stbi_uc *output;
1484
+ if (!data) return NULL;
1485
+ output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);
1410
1486
  if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }
1411
1487
  // compute number of non-alpha components
1412
1488
  if (comp & 1) n = comp; else n = comp-1;
@@ -2701,6 +2777,28 @@ static int stbi__process_scan_header(stbi__jpeg *z)
2701
2777
  return 1;
2702
2778
  }
2703
2779
 
2780
+ static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)
2781
+ {
2782
+ int i;
2783
+ for (i=0; i < ncomp; ++i) {
2784
+ if (z->img_comp[i].raw_data) {
2785
+ STBI_FREE(z->img_comp[i].raw_data);
2786
+ z->img_comp[i].raw_data = NULL;
2787
+ z->img_comp[i].data = NULL;
2788
+ }
2789
+ if (z->img_comp[i].raw_coeff) {
2790
+ STBI_FREE(z->img_comp[i].raw_coeff);
2791
+ z->img_comp[i].raw_coeff = 0;
2792
+ z->img_comp[i].coeff = 0;
2793
+ }
2794
+ if (z->img_comp[i].linebuf) {
2795
+ STBI_FREE(z->img_comp[i].linebuf);
2796
+ z->img_comp[i].linebuf = NULL;
2797
+ }
2798
+ }
2799
+ return why;
2800
+ }
2801
+
2704
2802
  static int stbi__process_frame_header(stbi__jpeg *z, int scan)
2705
2803
  {
2706
2804
  stbi__context *s = z->s;
@@ -2738,7 +2836,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
2738
2836
 
2739
2837
  if (scan != STBI__SCAN_load) return 1;
2740
2838
 
2741
- if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
2839
+ if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");
2742
2840
 
2743
2841
  for (i=0; i < s->img_n; ++i) {
2744
2842
  if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
@@ -2750,6 +2848,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
2750
2848
  z->img_v_max = v_max;
2751
2849
  z->img_mcu_w = h_max * 8;
2752
2850
  z->img_mcu_h = v_max * 8;
2851
+ // these sizes can't be more than 17 bits
2753
2852
  z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
2754
2853
  z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
2755
2854
 
@@ -2761,28 +2860,27 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
2761
2860
  // the bogus oversized data from using interleaved MCUs and their
2762
2861
  // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
2763
2862
  // discard the extra data until colorspace conversion
2863
+ //
2864
+ // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
2865
+ // so these muls can't overflow with 32-bit ints (which we require)
2764
2866
  z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
2765
2867
  z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
2766
- z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15);
2767
-
2768
- if (z->img_comp[i].raw_data == NULL) {
2769
- for(--i; i >= 0; --i) {
2770
- STBI_FREE(z->img_comp[i].raw_data);
2771
- z->img_comp[i].raw_data = NULL;
2772
- }
2773
- return stbi__err("outofmem", "Out of memory");
2774
- }
2868
+ z->img_comp[i].coeff = 0;
2869
+ z->img_comp[i].raw_coeff = 0;
2870
+ z->img_comp[i].linebuf = NULL;
2871
+ z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
2872
+ if (z->img_comp[i].raw_data == NULL)
2873
+ return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
2775
2874
  // align blocks for idct using mmx/sse
2776
2875
  z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
2777
- z->img_comp[i].linebuf = NULL;
2778
2876
  if (z->progressive) {
2779
- z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3;
2780
- z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3;
2781
- z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15);
2877
+ // w2, h2 are multiples of 8 (see above)
2878
+ z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
2879
+ z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
2880
+ z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
2881
+ if (z->img_comp[i].raw_coeff == NULL)
2882
+ return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
2782
2883
  z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
2783
- } else {
2784
- z->img_comp[i].coeff = 0;
2785
- z->img_comp[i].raw_coeff = 0;
2786
2884
  }
2787
2885
  }
2788
2886
 
@@ -3288,23 +3386,7 @@ static void stbi__setup_jpeg(stbi__jpeg *j)
3288
3386
  // clean up the temporary component buffers
3289
3387
  static void stbi__cleanup_jpeg(stbi__jpeg *j)
3290
3388
  {
3291
- int i;
3292
- for (i=0; i < j->s->img_n; ++i) {
3293
- if (j->img_comp[i].raw_data) {
3294
- STBI_FREE(j->img_comp[i].raw_data);
3295
- j->img_comp[i].raw_data = NULL;
3296
- j->img_comp[i].data = NULL;
3297
- }
3298
- if (j->img_comp[i].raw_coeff) {
3299
- STBI_FREE(j->img_comp[i].raw_coeff);
3300
- j->img_comp[i].raw_coeff = 0;
3301
- j->img_comp[i].coeff = 0;
3302
- }
3303
- if (j->img_comp[i].linebuf) {
3304
- STBI_FREE(j->img_comp[i].linebuf);
3305
- j->img_comp[i].linebuf = NULL;
3306
- }
3307
- }
3389
+ stbi__free_jpeg_components(j, j->s->img_n, 0);
3308
3390
  }
3309
3391
 
3310
3392
  typedef struct
@@ -3368,7 +3450,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
3368
3450
  }
3369
3451
 
3370
3452
  // can't error after this so, this is safe
3371
- output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1);
3453
+ output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
3372
3454
  if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
3373
3455
 
3374
3456
  // now go ahead and resample
@@ -3721,6 +3803,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
3721
3803
  int hlit = stbi__zreceive(a,5) + 257;
3722
3804
  int hdist = stbi__zreceive(a,5) + 1;
3723
3805
  int hclen = stbi__zreceive(a,4) + 4;
3806
+ int ntot = hlit + hdist;
3724
3807
 
3725
3808
  memset(codelength_sizes, 0, sizeof(codelength_sizes));
3726
3809
  for (i=0; i < hclen; ++i) {
@@ -3730,27 +3813,29 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
3730
3813
  if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
3731
3814
 
3732
3815
  n = 0;
3733
- while (n < hlit + hdist) {
3816
+ while (n < ntot) {
3734
3817
  int c = stbi__zhuffman_decode(a, &z_codelength);
3735
3818
  if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
3736
3819
  if (c < 16)
3737
3820
  lencodes[n++] = (stbi_uc) c;
3738
- else if (c == 16) {
3739
- c = stbi__zreceive(a,2)+3;
3740
- memset(lencodes+n, lencodes[n-1], c);
3741
- n += c;
3742
- } else if (c == 17) {
3743
- c = stbi__zreceive(a,3)+3;
3744
- memset(lencodes+n, 0, c);
3745
- n += c;
3746
- } else {
3747
- STBI_ASSERT(c == 18);
3748
- c = stbi__zreceive(a,7)+11;
3749
- memset(lencodes+n, 0, c);
3821
+ else {
3822
+ stbi_uc fill = 0;
3823
+ if (c == 16) {
3824
+ c = stbi__zreceive(a,2)+3;
3825
+ if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
3826
+ fill = lencodes[n-1];
3827
+ } else if (c == 17)
3828
+ c = stbi__zreceive(a,3)+3;
3829
+ else {
3830
+ STBI_ASSERT(c == 18);
3831
+ c = stbi__zreceive(a,7)+11;
3832
+ }
3833
+ if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
3834
+ memset(lencodes+n, fill, c);
3750
3835
  n += c;
3751
3836
  }
3752
3837
  }
3753
- if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG");
3838
+ if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");
3754
3839
  if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
3755
3840
  if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
3756
3841
  return 1;
@@ -4016,7 +4101,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
4016
4101
  int width = x;
4017
4102
 
4018
4103
  STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
4019
- a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into
4104
+ a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
4020
4105
  if (!a->out) return stbi__err("outofmem", "Out of memory");
4021
4106
 
4022
4107
  img_width_bytes = (((img_n * x * depth) + 7) >> 3);
@@ -4214,13 +4299,15 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
4214
4299
 
4215
4300
  static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)
4216
4301
  {
4302
+ int bytes = (depth == 16 ? 2 : 1);
4303
+ int out_bytes = out_n * bytes;
4217
4304
  stbi_uc *final;
4218
4305
  int p;
4219
4306
  if (!interlaced)
4220
4307
  return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
4221
4308
 
4222
4309
  // de-interlacing
4223
- final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n);
4310
+ final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
4224
4311
  for (p=0; p < 7; ++p) {
4225
4312
  int xorig[] = { 0,4,0,2,0,1,0 };
4226
4313
  int yorig[] = { 0,0,4,0,2,0,1 };
@@ -4240,8 +4327,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3
4240
4327
  for (i=0; i < x; ++i) {
4241
4328
  int out_y = j*yspc[p]+yorig[p];
4242
4329
  int out_x = i*xspc[p]+xorig[p];
4243
- memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n,
4244
- a->out + (j*x+i)*out_n, out_n);
4330
+ memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,
4331
+ a->out + (j*x+i)*out_bytes, out_bytes);
4245
4332
  }
4246
4333
  }
4247
4334
  STBI_FREE(a->out);
@@ -4309,7 +4396,7 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
4309
4396
  stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
4310
4397
  stbi_uc *p, *temp_out, *orig = a->out;
4311
4398
 
4312
- p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n);
4399
+ p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);
4313
4400
  if (p == NULL) return stbi__err("outofmem", "Out of memory");
4314
4401
 
4315
4402
  // between here and free(out) below, exitting would leak
@@ -4351,9 +4438,10 @@ static int stbi__reduce_png(stbi__png *p)
4351
4438
  if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data
4352
4439
 
4353
4440
  reduced = (stbi_uc *)stbi__malloc(img_len);
4354
- if (p == NULL) return stbi__err("outofmem", "Out of memory");
4441
+ if (reduced == NULL) return stbi__err("outofmem", "Out of memory");
4355
4442
 
4356
- for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling
4443
+ for (i = 0; i < img_len; ++i)
4444
+ reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling
4357
4445
 
4358
4446
  p->out = reduced;
4359
4447
  STBI_FREE(orig);
@@ -4843,7 +4931,11 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
4843
4931
  else
4844
4932
  target = s->img_n; // if they want monochrome, we'll post-convert
4845
4933
 
4846
- out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y);
4934
+ // sanity-check size
4935
+ if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
4936
+ return stbi__errpuc("too large", "Corrupt BMP");
4937
+
4938
+ out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
4847
4939
  if (!out) return stbi__errpuc("outofmem", "Out of memory");
4848
4940
  if (info.bpp < 16) {
4849
4941
  int z=0;
@@ -5143,7 +5235,10 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
5143
5235
  *y = tga_height;
5144
5236
  if (comp) *comp = tga_comp;
5145
5237
 
5146
- tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp );
5238
+ if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
5239
+ return stbi__errpuc("too large", "Corrupt TGA");
5240
+
5241
+ tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
5147
5242
  if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
5148
5243
 
5149
5244
  // skip to the data's starting position (offset usually = 0)
@@ -5162,7 +5257,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
5162
5257
  // any data to skip? (offset usually = 0)
5163
5258
  stbi__skip(s, tga_palette_start );
5164
5259
  // load the palette
5165
- tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp );
5260
+ tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
5166
5261
  if (!tga_palette) {
5167
5262
  STBI_FREE(tga_data);
5168
5263
  return stbi__errpuc("outofmem", "Out of memory");
@@ -5298,11 +5393,49 @@ static int stbi__psd_test(stbi__context *s)
5298
5393
  return r;
5299
5394
  }
5300
5395
 
5396
+ static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
5397
+ {
5398
+ int count, nleft, len;
5399
+
5400
+ count = 0;
5401
+ while ((nleft = pixelCount - count) > 0) {
5402
+ len = stbi__get8(s);
5403
+ if (len == 128) {
5404
+ // No-op.
5405
+ } else if (len < 128) {
5406
+ // Copy next len+1 bytes literally.
5407
+ len++;
5408
+ if (len > nleft) return 0; // corrupt data
5409
+ count += len;
5410
+ while (len) {
5411
+ *p = stbi__get8(s);
5412
+ p += 4;
5413
+ len--;
5414
+ }
5415
+ } else if (len > 128) {
5416
+ stbi_uc val;
5417
+ // Next -len+1 bytes in the dest are replicated from next source byte.
5418
+ // (Interpret len as a negative 8-bit int.)
5419
+ len = 257 - len;
5420
+ if (len > nleft) return 0; // corrupt data
5421
+ val = stbi__get8(s);
5422
+ count += len;
5423
+ while (len) {
5424
+ *p = val;
5425
+ p += 4;
5426
+ len--;
5427
+ }
5428
+ }
5429
+ }
5430
+
5431
+ return 1;
5432
+ }
5433
+
5301
5434
  static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
5302
5435
  {
5303
- int pixelCount;
5436
+ int pixelCount;
5304
5437
  int channelCount, compression;
5305
- int channel, i, count, len;
5438
+ int channel, i;
5306
5439
  int bitdepth;
5307
5440
  int w,h;
5308
5441
  stbi_uc *out;
@@ -5362,8 +5495,12 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
5362
5495
  if (compression > 1)
5363
5496
  return stbi__errpuc("bad compression", "PSD has an unknown compression format");
5364
5497
 
5498
+ // Check size
5499
+ if (!stbi__mad3sizes_valid(4, w, h, 0))
5500
+ return stbi__errpuc("too large", "Corrupt PSD");
5501
+
5365
5502
  // Create the destination image.
5366
- out = (stbi_uc *) stbi__malloc(4 * w*h);
5503
+ out = (stbi_uc *) stbi__malloc_mad3(4, w, h, 0);
5367
5504
  if (!out) return stbi__errpuc("outofmem", "Out of memory");
5368
5505
  pixelCount = w*h;
5369
5506
 
@@ -5395,34 +5532,9 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
5395
5532
  *p = (channel == 3 ? 255 : 0);
5396
5533
  } else {
5397
5534
  // Read the RLE data.
5398
- count = 0;
5399
- while (count < pixelCount) {
5400
- len = stbi__get8(s);
5401
- if (len == 128) {
5402
- // No-op.
5403
- } else if (len < 128) {
5404
- // Copy next len+1 bytes literally.
5405
- len++;
5406
- count += len;
5407
- while (len) {
5408
- *p = stbi__get8(s);
5409
- p += 4;
5410
- len--;
5411
- }
5412
- } else if (len > 128) {
5413
- stbi_uc val;
5414
- // Next -len+1 bytes in the dest are replicated from next source byte.
5415
- // (Interpret len as a negative 8-bit int.)
5416
- len ^= 0x0FF;
5417
- len += 2;
5418
- val = stbi__get8(s);
5419
- count += len;
5420
- while (len) {
5421
- *p = val;
5422
- p += 4;
5423
- len--;
5424
- }
5425
- }
5535
+ if (!stbi__psd_decode_rle(s, p, pixelCount)) {
5536
+ STBI_FREE(out);
5537
+ return stbi__errpuc("corrupt", "bad RLE data");
5426
5538
  }
5427
5539
  }
5428
5540
  }
@@ -5665,14 +5777,14 @@ static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int re
5665
5777
  x = stbi__get16be(s);
5666
5778
  y = stbi__get16be(s);
5667
5779
  if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)");
5668
- if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode");
5780
+ if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
5669
5781
 
5670
5782
  stbi__get32be(s); //skip `ratio'
5671
5783
  stbi__get16be(s); //skip `fields'
5672
5784
  stbi__get16be(s); //skip `pad'
5673
5785
 
5674
5786
  // intermediate buffer is RGBA
5675
- result = (stbi_uc *) stbi__malloc(x*y*4);
5787
+ result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
5676
5788
  memset(result, 0xff, x*y*4);
5677
5789
 
5678
5790
  if (!stbi__pic_load_core(s,x,y,comp, result)) {
@@ -5931,8 +6043,11 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
5931
6043
  if (g->out == 0 && !stbi__gif_header(s, g, comp,0))
5932
6044
  return 0; // stbi__g_failure_reason set by stbi__gif_header
5933
6045
 
6046
+ if (!stbi__mad3sizes_valid(g->w, g->h, 4, 0))
6047
+ return stbi__errpuc("too large", "GIF too large");
6048
+
5934
6049
  prev_out = g->out;
5935
- g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
6050
+ g->out = (stbi_uc *) stbi__malloc_mad3(4, g->w, g->h, 0);
5936
6051
  if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
5937
6052
 
5938
6053
  switch ((g->eflags & 0x1C) >> 2) {
@@ -6179,8 +6294,13 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
6179
6294
  if (comp) *comp = 3;
6180
6295
  if (req_comp == 0) req_comp = 3;
6181
6296
 
6297
+ if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
6298
+ return stbi__errpf("too large", "HDR image is too large");
6299
+
6182
6300
  // Read data
6183
- hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float));
6301
+ hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
6302
+ if (!hdr_data)
6303
+ return stbi__errpf("outofmem", "Out of memory");
6184
6304
 
6185
6305
  // Load image data
6186
6306
  // image data is stored as some number of sca
@@ -6219,20 +6339,29 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
6219
6339
  len <<= 8;
6220
6340
  len |= stbi__get8(s);
6221
6341
  if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
6222
- if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4);
6342
+ if (scanline == NULL) {
6343
+ scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
6344
+ if (!scanline) {
6345
+ STBI_FREE(hdr_data);
6346
+ return stbi__errpf("outofmem", "Out of memory");
6347
+ }
6348
+ }
6223
6349
 
6224
6350
  for (k = 0; k < 4; ++k) {
6351
+ int nleft;
6225
6352
  i = 0;
6226
- while (i < width) {
6353
+ while ((nleft = width - i) > 0) {
6227
6354
  count = stbi__get8(s);
6228
6355
  if (count > 128) {
6229
6356
  // Run
6230
6357
  value = stbi__get8(s);
6231
6358
  count -= 128;
6359
+ if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
6232
6360
  for (z = 0; z < count; ++z)
6233
6361
  scanline[i++ * 4 + k] = value;
6234
6362
  } else {
6235
6363
  // Dump
6364
+ if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
6236
6365
  for (z = 0; z < count; ++z)
6237
6366
  scanline[i++ * 4 + k] = stbi__get8(s);
6238
6367
  }
@@ -6241,7 +6370,8 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
6241
6370
  for (i=0; i < width; ++i)
6242
6371
  stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
6243
6372
  }
6244
- STBI_FREE(scanline);
6373
+ if (scanline)
6374
+ STBI_FREE(scanline);
6245
6375
  }
6246
6376
 
6247
6377
  return hdr_data;
@@ -6428,7 +6558,10 @@ static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int
6428
6558
  *y = s->img_y;
6429
6559
  *comp = s->img_n;
6430
6560
 
6431
- out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y);
6561
+ if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
6562
+ return stbi__errpuc("too large", "PNM too large");
6563
+
6564
+ out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
6432
6565
  if (!out) return stbi__errpuc("outofmem", "Out of memory");
6433
6566
  stbi__getn(s, out, s->img_n * s->img_x * s->img_y);
6434
6567