Cluster.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "Cluster.h"
  2. #include "read.h"
  3. #include "global_elements.h"
  4. #include <winsock.h>
  5. // returns bytes read. 0 means EOF
  6. uint64_t nsmkv::ReadBlockGroup(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Block &block, uint64_t *allowed_track_numbers, size_t num_allowed_track_numbers)
  7. {
  8. uint64_t total_bytes_read=0;
  9. while (size)
  10. {
  11. uint64_t ebml_start_position = reader->Tell(); // need this for recording the block binary start position
  12. ebml_node node;
  13. uint64_t bytes_read = read_ebml_node(reader, &node);
  14. if (bytes_read == 0)
  15. return 0;
  16. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  17. if (bytes_read > size)
  18. return 0;
  19. total_bytes_read+=bytes_read;
  20. size-=bytes_read;
  21. if (node.size > size)
  22. return 0;
  23. total_bytes_read+=node.size;
  24. size-=node.size;
  25. switch(node.id)
  26. {
  27. case mkv_blockgroup_referenceblock:
  28. {
  29. int64_t val;
  30. if (read_signed(reader, node.size, &val) == 0)
  31. return 0;
  32. #ifdef WA_VALIDATE
  33. printf(" Reference Block: %I64d\n", val);
  34. #endif
  35. block.reference_block = val;
  36. }
  37. break;
  38. case mkv_blockgroup_block:
  39. {
  40. #ifdef WA_VALIDATE
  41. printf(" Block: binary size %I64u\n", node.size);
  42. #endif
  43. if (ReadBlockBinary(reader, node.size, block.binary, allowed_track_numbers, num_allowed_track_numbers) == 0)
  44. return 0;
  45. }
  46. break;
  47. case mkv_blockgroup_blockduration:
  48. {
  49. uint64_t val;
  50. if (read_unsigned(reader, node.size, &val) == 0)
  51. return 0;
  52. #ifdef WA_VALIDATE
  53. printf(" Block Duration: %I64u\n", val);
  54. #endif
  55. block.block_duration = val;
  56. }
  57. break;
  58. default:
  59. nsmkv::ReadGlobal(reader, node.id, node.size);
  60. }
  61. }
  62. return total_bytes_read;
  63. }
  64. // returns bytes read. 0 means EOF
  65. uint64_t nsmkv::ReadCluster(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Cluster &cluster)
  66. {
  67. uint64_t total_bytes_read=0;
  68. while (size)
  69. {
  70. ebml_node node;
  71. uint64_t bytes_read = read_ebml_node(reader, &node);
  72. if (bytes_read == 0)
  73. return 0;
  74. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  75. if (bytes_read > size)
  76. return 0;
  77. total_bytes_read+=bytes_read;
  78. size-=bytes_read;
  79. if (node.size > size)
  80. return 0;
  81. total_bytes_read+=node.size;
  82. size-=node.size;
  83. switch(node.id)
  84. {
  85. case mkv_cluster_timecode:
  86. {
  87. uint64_t val;
  88. if (read_unsigned(reader, node.size, &val) == 0)
  89. return 0;
  90. #ifdef WA_VALIDATE
  91. printf(" Time Code: %I64u\n", val);
  92. cluster.time_code_found = true;
  93. #endif
  94. cluster.time_code = val;
  95. }
  96. break;
  97. case mkv_cluster_blockgroup:
  98. {
  99. #ifdef WA_VALIDATE
  100. printf(" Block Group\n");
  101. #endif
  102. Block block;
  103. if (ReadBlockGroup(reader, node.size, block, 0, 0) == 0)
  104. return 0;
  105. }
  106. break;
  107. case mkv_cluster_simpleblock:
  108. {
  109. #ifdef WA_VALIDATE
  110. printf(" Simple Block, size: %I64u\n", node.size);
  111. #endif
  112. BlockBinary bbinary;
  113. if (ReadBlockBinary(reader, node.size, bbinary, 0, 0) == 0)
  114. return 0;
  115. // fseek64(f, node.size, SEEK_CUR);
  116. }
  117. break;
  118. default:
  119. ReadGlobal(reader, node.id, node.size);
  120. }
  121. }
  122. return total_bytes_read;
  123. }
  124. uint64_t nsmkv::ReadBlockBinary(nsmkv::MKVReader *reader, uint64_t size, nsmkv::BlockBinary &binary, uint64_t *allowed_track_numbers, size_t num_allowed_track_numbers)
  125. {
  126. uint64_t orig_size = size;
  127. size_t bytes_read = (size_t)read_vint(reader, &binary.track_number);
  128. if (!bytes_read)
  129. return 0;
  130. size-=bytes_read;
  131. bool allowed_track=false;
  132. if (num_allowed_track_numbers == (size_t)-1)
  133. {
  134. allowed_track=true;
  135. }
  136. else
  137. {
  138. for (size_t i=0;i!=num_allowed_track_numbers;i++)
  139. {
  140. if (binary.track_number == allowed_track_numbers[i])
  141. {
  142. allowed_track=true;
  143. break;
  144. }
  145. }
  146. }
  147. #ifdef WA_VALIDATE
  148. // if we are validating the file, force all tracks to go thru
  149. allowed_track = true;
  150. #endif
  151. if (allowed_track && size >= 3)
  152. {
  153. uint16_t time_code_endian;
  154. size_t bytes_read;
  155. reader->Read(&time_code_endian, sizeof(uint16_t), &bytes_read);
  156. if (bytes_read != sizeof(uint16_t))
  157. return 0;
  158. binary.time_code = htons(time_code_endian);
  159. size-=sizeof(uint16_t);
  160. uint8_t flags;
  161. reader->Read(&flags, 1, &bytes_read);
  162. if (bytes_read != 1)
  163. return 0;
  164. binary.flags = flags;
  165. size -= sizeof(uint8_t);
  166. binary.data_size = (size_t)size;
  167. #ifndef WA_VALIDATE
  168. binary.data = malloc((size_t)size);
  169. if (!binary.data)
  170. return 0;
  171. reader->Read(binary.data, (size_t)size, &bytes_read);
  172. if (bytes_read != size)
  173. {
  174. free(binary.data);
  175. return 0;
  176. }
  177. #else
  178. printf(" track number = %I64u\n",binary.track_number);
  179. printf(" timecode = %u\n",binary.time_code);
  180. printf(" flags = %u\n",binary.flags);
  181. printf(" data_size = %I64u\n",size);
  182. // if we are validating the nmk file we don't need to
  183. // actually read the data, just skip past it
  184. //fseek(reader, size, SEEK_CUR);
  185. #endif
  186. return orig_size;
  187. }
  188. else
  189. {
  190. reader->Skip(size);
  191. return orig_size;
  192. }
  193. return 0;
  194. }