gosu 0.10.7 → 0.10.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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