| 71 | |
| 72 | |
| 73 | void Unpack::Init(size_t WinSize,bool Solid) |
| 74 | { |
| 75 | // If 32-bit RAR unpacks an archive with 4 GB dictionary, the window size |
| 76 | // will be 0 because of size_t overflow. Let's issue the memory error. |
| 77 | if (WinSize==0) |
| 78 | ErrHandler.MemoryError(); |
| 79 | |
| 80 | // Minimum window size must be at least twice more than maximum possible |
| 81 | // size of filter block, which is 0x10000 in RAR now. If window size is |
| 82 | // smaller, we can have a block with never cleared flt->NextWindow flag |
| 83 | // in UnpWriteBuf(). Minimum window size 0x20000 would be enough, but let's |
| 84 | // use 0x40000 for extra safety and possible filter area size expansion. |
| 85 | const size_t MinAllocSize=0x40000; |
| 86 | if (WinSize<MinAllocSize) |
| 87 | WinSize=MinAllocSize; |
| 88 | |
| 89 | if (WinSize<=MaxWinSize) // Use the already allocated window. |
| 90 | return; |
| 91 | if ((WinSize>>16)>0x10000) // Window size must not exceed 4 GB. |
| 92 | return; |
| 93 | |
| 94 | // Archiving code guarantees that window size does not grow in the same |
| 95 | // solid stream. So if we are here, we are either creating a new window |
| 96 | // or increasing the size of non-solid window. So we could safely reject |
| 97 | // current window data without copying them to a new window, though being |
| 98 | // extra cautious, we still handle the solid window grow case below. |
| 99 | bool Grow=Solid && (Window!=NULL || Fragmented); |
| 100 | |
| 101 | // We do not handle growth for existing fragmented window. |
| 102 | if (Grow && Fragmented) |
| 103 | throw std::bad_alloc(); |
| 104 | |
| 105 | byte *NewWindow=Fragmented ? NULL : (byte *)malloc(WinSize); |
| 106 | |
| 107 | if (NewWindow==NULL) |
| 108 | if (Grow || WinSize<0x1000000) |
| 109 | { |
| 110 | // We do not support growth for new fragmented window. |
| 111 | // Also exclude RAR4 and small dictionaries. |
| 112 | throw std::bad_alloc(); |
| 113 | } |
| 114 | else |
| 115 | { |
| 116 | if (Window!=NULL) // If allocated by preceding files. |
| 117 | { |
| 118 | free(Window); |
| 119 | Window=NULL; |
| 120 | } |
| 121 | FragWindow.Init(WinSize); |
| 122 | Fragmented=true; |
| 123 | } |
| 124 | |
| 125 | if (!Fragmented) |
| 126 | { |
| 127 | // Clean the window to generate the same output when unpacking corrupt |
| 128 | // RAR files, which may access unused areas of sliding dictionary. |
| 129 | memset(NewWindow,0,WinSize); |
| 130 |
nothing calls this directly
no test coverage detected