mirror of
https://github.com/Q3Rally-Team/q3rally.git
synced 2025-01-24 02:11:01 +00:00
0d5fb492cd
Fix GCC 6 misleading-indentation warning add SECURITY.md OpenGL2: Restore adding fixed ambient light when HDR is enabled Few LCC memory fixes. fix a few potential buffer overwrite in Game VM Enable compiler optimization on all macOS architectures Don't allow qagame module to create "botlib.log" at ANY filesystem location Make FS_BuildOSPath for botlib.log consistent with typical usage tiny readme thing Remove extra plus sign from Huff_Compress() Fix VMs being able to change CVAR_PROTECTED cvars Don't register fs_game cvar everywhere just to get the value Don't let VMs change engine latch cvars immediately Fix fs_game '..' reading outside of home and base path Fix VMs forcing engine latch cvar to update to latched value Revert my recent cvar latch changes Revert "Don't let VMs change engine latch cvars immediately" Partially revert "Fix fs_game '..' reading outside of home and base path" Revert "Fix VMs forcing engine latch cvar to update to latched value" Fix exploit to bypass filename restrictions on Windows Changes to systemd q3a.service Fix Q_vsnprintf for mingw-w64 Fix timelimit causing an infinite map ending loop Fix invalid access to cluster 0 in AAS_AreaRouteToGoalArea() Fix negative frag/capturelimit causing an infinite map end loop OpenGL2: Fix dark lightmap on shader in mpteam6 Make FS_InvalidGameDir() consider subdirectories invalid [qcommon] Remove dead serialization code [qcommon] Make several zone variables and functions static. Fix MAC_OS_X_VERSION_MIN_REQUIRED for macOS 10.10 and later Increase q3_ui .arena filename list buffer size to 4096 bytes OpenGL2: Fix crash when BSP has deluxe maps and vertex lit surfaces Support Unicode characters greater than 0xFF in cl_consoleKeys Fix macOS app bundle with space in name OpenGL1: Use glGenTextures instead of hardcoded values Remove CON_FlushIn function and where STDIN needs flushing, use tcflush POSIX function Update libogg from 1.3.2 to 1.3.3 Rename (already updated) libogg-1.3.2 to libogg-1.3.3 Update libvorbis from 1.3.5 to 1.3.6 * Fix CVE-2018-5146 - out-of-bounds write on codebook decoding. * Fix CVE-2017-14632 - free() on unitialized data * Fix CVE-2017-14633 - out-of-bounds read Rename (already updated) libvorbis-1.3.5 to libvorbis-1.3.6 Update opus from 1.1.4 to 1.2.1 Rename (already updated) opus-1.1.4 to opus-1.2.1 Update opusfile from 0.8 to 0.9 Rename (already updated) opusfile-0.8 to opusfile-0.9 First swing at a CONTRIBUTING.md Allow loading system OpenAL library on macOS again Remove duplicate setting of FREETYPE_CFLAGS in Makefile Fix exploit to reset player by sending wrong serverId Fix "Going to CS_ZOMBIE for [clientname]" developer message Fix MSG_Read*String*() functions not being able to read last byte from message
364 lines
12 KiB
C
364 lines
12 KiB
C
/********************************************************************
|
|
* *
|
|
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
|
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
|
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
|
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
|
* *
|
|
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 *
|
|
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
|
|
* *
|
|
********************************************************************
|
|
|
|
function: stdio-based convenience library for opening/seeking/decoding
|
|
last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $
|
|
|
|
********************************************************************/
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "internal.h"
|
|
#include <sys/types.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#if defined(_WIN32)
|
|
# include <io.h>
|
|
#endif
|
|
|
|
typedef struct OpusMemStream OpusMemStream;
|
|
|
|
#define OP_MEM_SIZE_MAX (~(size_t)0>>1)
|
|
#define OP_MEM_DIFF_MAX ((ptrdiff_t)OP_MEM_SIZE_MAX)
|
|
|
|
/*The context information needed to read from a block of memory as if it were a
|
|
file.*/
|
|
struct OpusMemStream{
|
|
/*The block of memory to read from.*/
|
|
const unsigned char *data;
|
|
/*The total size of the block.
|
|
This must be at most OP_MEM_SIZE_MAX to prevent signed overflow while
|
|
seeking.*/
|
|
ptrdiff_t size;
|
|
/*The current file position.
|
|
This is allowed to be set arbitrarily greater than size (i.e., past the end
|
|
of the block, though we will not read data past the end of the block), but
|
|
is not allowed to be negative (i.e., before the beginning of the block).*/
|
|
ptrdiff_t pos;
|
|
};
|
|
|
|
static int op_fread(void *_stream,unsigned char *_ptr,int _buf_size){
|
|
FILE *stream;
|
|
size_t ret;
|
|
/*Check for empty read.*/
|
|
if(_buf_size<=0)return 0;
|
|
stream=(FILE *)_stream;
|
|
ret=fread(_ptr,1,_buf_size,stream);
|
|
OP_ASSERT(ret<=(size_t)_buf_size);
|
|
/*If ret==0 and !feof(stream), there was a read error.*/
|
|
return ret>0||feof(stream)?(int)ret:OP_EREAD;
|
|
}
|
|
|
|
static int op_fseek(void *_stream,opus_int64 _offset,int _whence){
|
|
#if defined(_WIN32)
|
|
/*_fseeki64() is not exposed until MSCVCRT80.
|
|
This is the default starting with MSVC 2005 (_MSC_VER>=1400), but we want
|
|
to allow linking against older MSVCRT versions for compatibility back to
|
|
XP without installing extra runtime libraries.
|
|
i686-pc-mingw32 does not have fseeko() and requires
|
|
__MSVCRT_VERSION__>=0x800 for _fseeki64(), which screws up linking with
|
|
other libraries (that don't use MSVCRT80 from MSVC 2005 by default).
|
|
i686-w64-mingw32 does have fseeko() and respects _FILE_OFFSET_BITS, but I
|
|
don't know how to detect that at compile time.
|
|
We could just use fseeko64() (which is available in both), but its
|
|
implemented using fgetpos()/fsetpos() just like this code, except without
|
|
the overflow checking, so we prefer our version.*/
|
|
opus_int64 pos;
|
|
/*We don't use fpos_t directly because it might be a struct if __STDC__ is
|
|
non-zero or _INTEGRAL_MAX_BITS < 64.
|
|
I'm not certain when the latter is true, but someone could in theory set
|
|
the former.
|
|
Either way, it should be binary compatible with a normal 64-bit int (this
|
|
assumption is not portable, but I believe it is true for MSVCRT).*/
|
|
OP_ASSERT(sizeof(pos)==sizeof(fpos_t));
|
|
/*Translate the seek to an absolute one.*/
|
|
if(_whence==SEEK_CUR){
|
|
int ret;
|
|
ret=fgetpos((FILE *)_stream,(fpos_t *)&pos);
|
|
if(ret)return ret;
|
|
}
|
|
else if(_whence==SEEK_END)pos=_filelengthi64(_fileno((FILE *)_stream));
|
|
else if(_whence==SEEK_SET)pos=0;
|
|
else return -1;
|
|
/*Check for errors or overflow.*/
|
|
if(pos<0||_offset<-pos||_offset>OP_INT64_MAX-pos)return -1;
|
|
pos+=_offset;
|
|
return fsetpos((FILE *)_stream,(fpos_t *)&pos);
|
|
#else
|
|
/*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer
|
|
it except on Windows.*/
|
|
return fseeko((FILE *)_stream,(off_t)_offset,_whence);
|
|
#endif
|
|
}
|
|
|
|
static opus_int64 op_ftell(void *_stream){
|
|
#if defined(_WIN32)
|
|
/*_ftelli64() is not exposed until MSCVCRT80, and ftello()/ftello64() have
|
|
the same problems as fseeko()/fseeko64() in MingW.
|
|
See above for a more detailed explanation.*/
|
|
opus_int64 pos;
|
|
OP_ASSERT(sizeof(pos)==sizeof(fpos_t));
|
|
return fgetpos((FILE *)_stream,(fpos_t *)&pos)?-1:pos;
|
|
#else
|
|
/*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer
|
|
it except on Windows.*/
|
|
return ftello((FILE *)_stream);
|
|
#endif
|
|
}
|
|
|
|
static const OpusFileCallbacks OP_FILE_CALLBACKS={
|
|
op_fread,
|
|
op_fseek,
|
|
op_ftell,
|
|
(op_close_func)fclose
|
|
};
|
|
|
|
#if defined(_WIN32)
|
|
# include <stddef.h>
|
|
# include <errno.h>
|
|
|
|
/*Windows doesn't accept UTF-8 by default, and we don't have a wchar_t API,
|
|
so if we just pass the path to fopen(), then there'd be no way for a user
|
|
of our API to open a Unicode filename.
|
|
Instead, we translate from UTF-8 to UTF-16 and use Windows' wchar_t API.
|
|
This makes this API more consistent with platforms where the character set
|
|
used by fopen is the same as used on disk, which is generally UTF-8, and
|
|
with our metadata API, which always uses UTF-8.*/
|
|
static wchar_t *op_utf8_to_utf16(const char *_src){
|
|
wchar_t *dst;
|
|
size_t len;
|
|
len=strlen(_src);
|
|
/*Worst-case output is 1 wide character per 1 input character.*/
|
|
dst=(wchar_t *)_ogg_malloc(sizeof(*dst)*(len+1));
|
|
if(dst!=NULL){
|
|
size_t si;
|
|
size_t di;
|
|
for(di=si=0;si<len;si++){
|
|
int c0;
|
|
c0=(unsigned char)_src[si];
|
|
if(!(c0&0x80)){
|
|
/*Start byte says this is a 1-byte sequence.*/
|
|
dst[di++]=(wchar_t)c0;
|
|
continue;
|
|
}
|
|
else{
|
|
int c1;
|
|
/*This is safe, because c0 was not 0 and _src is NUL-terminated.*/
|
|
c1=(unsigned char)_src[si+1];
|
|
if((c1&0xC0)==0x80){
|
|
/*Found at least one continuation byte.*/
|
|
if((c0&0xE0)==0xC0){
|
|
wchar_t w;
|
|
/*Start byte says this is a 2-byte sequence.*/
|
|
w=(c0&0x1F)<<6|c1&0x3F;
|
|
if(w>=0x80U){
|
|
/*This is a 2-byte sequence that is not overlong.*/
|
|
dst[di++]=w;
|
|
si++;
|
|
continue;
|
|
}
|
|
}
|
|
else{
|
|
int c2;
|
|
/*This is safe, because c1 was not 0 and _src is NUL-terminated.*/
|
|
c2=(unsigned char)_src[si+2];
|
|
if((c2&0xC0)==0x80){
|
|
/*Found at least two continuation bytes.*/
|
|
if((c0&0xF0)==0xE0){
|
|
wchar_t w;
|
|
/*Start byte says this is a 3-byte sequence.*/
|
|
w=(c0&0xF)<<12|(c1&0x3F)<<6|c2&0x3F;
|
|
if(w>=0x800U&&(w<0xD800||w>=0xE000)&&w<0xFFFE){
|
|
/*This is a 3-byte sequence that is not overlong, not a
|
|
UTF-16 surrogate pair value, and not a 'not a character'
|
|
value.*/
|
|
dst[di++]=w;
|
|
si+=2;
|
|
continue;
|
|
}
|
|
}
|
|
else{
|
|
int c3;
|
|
/*This is safe, because c2 was not 0 and _src is
|
|
NUL-terminated.*/
|
|
c3=(unsigned char)_src[si+3];
|
|
if((c3&0xC0)==0x80){
|
|
/*Found at least three continuation bytes.*/
|
|
if((c0&0xF8)==0xF0){
|
|
opus_uint32 w;
|
|
/*Start byte says this is a 4-byte sequence.*/
|
|
w=(c0&7)<<18|(c1&0x3F)<<12|(c2&0x3F)<<6&(c3&0x3F);
|
|
if(w>=0x10000U&&w<0x110000U){
|
|
/*This is a 4-byte sequence that is not overlong and not
|
|
greater than the largest valid Unicode code point.
|
|
Convert it to a surrogate pair.*/
|
|
w-=0x10000;
|
|
dst[di++]=(wchar_t)(0xD800+(w>>10));
|
|
dst[di++]=(wchar_t)(0xDC00+(w&0x3FF));
|
|
si+=3;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*If we got here, we encountered an illegal UTF-8 sequence.*/
|
|
_ogg_free(dst);
|
|
return NULL;
|
|
}
|
|
OP_ASSERT(di<=len);
|
|
dst[di]='\0';
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
#endif
|
|
|
|
void *op_fopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode){
|
|
FILE *fp;
|
|
#if !defined(_WIN32)
|
|
fp=fopen(_path,_mode);
|
|
#else
|
|
fp=NULL;
|
|
{
|
|
wchar_t *wpath;
|
|
wchar_t *wmode;
|
|
wpath=op_utf8_to_utf16(_path);
|
|
wmode=op_utf8_to_utf16(_mode);
|
|
if(wmode==NULL)errno=EINVAL;
|
|
else if(wpath==NULL)errno=ENOENT;
|
|
else fp=_wfopen(wpath,wmode);
|
|
_ogg_free(wmode);
|
|
_ogg_free(wpath);
|
|
}
|
|
#endif
|
|
if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS;
|
|
return fp;
|
|
}
|
|
|
|
void *op_fdopen(OpusFileCallbacks *_cb,int _fd,const char *_mode){
|
|
FILE *fp;
|
|
fp=fdopen(_fd,_mode);
|
|
if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS;
|
|
return fp;
|
|
}
|
|
|
|
void *op_freopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode,
|
|
void *_stream){
|
|
FILE *fp;
|
|
#if !defined(_WIN32)
|
|
fp=freopen(_path,_mode,(FILE *)_stream);
|
|
#else
|
|
fp=NULL;
|
|
{
|
|
wchar_t *wpath;
|
|
wchar_t *wmode;
|
|
wpath=op_utf8_to_utf16(_path);
|
|
wmode=op_utf8_to_utf16(_mode);
|
|
if(wmode==NULL)errno=EINVAL;
|
|
else if(wpath==NULL)errno=ENOENT;
|
|
else fp=_wfreopen(wpath,wmode,(FILE *)_stream);
|
|
_ogg_free(wmode);
|
|
_ogg_free(wpath);
|
|
}
|
|
#endif
|
|
if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS;
|
|
return fp;
|
|
}
|
|
|
|
static int op_mem_read(void *_stream,unsigned char *_ptr,int _buf_size){
|
|
OpusMemStream *stream;
|
|
ptrdiff_t size;
|
|
ptrdiff_t pos;
|
|
stream=(OpusMemStream *)_stream;
|
|
/*Check for empty read.*/
|
|
if(_buf_size<=0)return 0;
|
|
size=stream->size;
|
|
pos=stream->pos;
|
|
/*Check for EOF.*/
|
|
if(pos>=size)return 0;
|
|
/*Check for a short read.*/
|
|
_buf_size=(int)OP_MIN(size-pos,_buf_size);
|
|
memcpy(_ptr,stream->data+pos,_buf_size);
|
|
pos+=_buf_size;
|
|
stream->pos=pos;
|
|
return _buf_size;
|
|
}
|
|
|
|
static int op_mem_seek(void *_stream,opus_int64 _offset,int _whence){
|
|
OpusMemStream *stream;
|
|
ptrdiff_t pos;
|
|
stream=(OpusMemStream *)_stream;
|
|
pos=stream->pos;
|
|
OP_ASSERT(pos>=0);
|
|
switch(_whence){
|
|
case SEEK_SET:{
|
|
/*Check for overflow:*/
|
|
if(_offset<0||_offset>OP_MEM_DIFF_MAX)return -1;
|
|
pos=(ptrdiff_t)_offset;
|
|
}break;
|
|
case SEEK_CUR:{
|
|
/*Check for overflow:*/
|
|
if(_offset<-pos||_offset>OP_MEM_DIFF_MAX-pos)return -1;
|
|
pos=(ptrdiff_t)(pos+_offset);
|
|
}break;
|
|
case SEEK_END:{
|
|
ptrdiff_t size;
|
|
size=stream->size;
|
|
OP_ASSERT(size>=0);
|
|
/*Check for overflow:*/
|
|
if(_offset>size||_offset<size-OP_MEM_DIFF_MAX)return -1;
|
|
pos=(ptrdiff_t)(size-_offset);
|
|
}break;
|
|
default:return -1;
|
|
}
|
|
stream->pos=pos;
|
|
return 0;
|
|
}
|
|
|
|
static opus_int64 op_mem_tell(void *_stream){
|
|
OpusMemStream *stream;
|
|
stream=(OpusMemStream *)_stream;
|
|
return (ogg_int64_t)stream->pos;
|
|
}
|
|
|
|
static int op_mem_close(void *_stream){
|
|
_ogg_free(_stream);
|
|
return 0;
|
|
}
|
|
|
|
static const OpusFileCallbacks OP_MEM_CALLBACKS={
|
|
op_mem_read,
|
|
op_mem_seek,
|
|
op_mem_tell,
|
|
op_mem_close
|
|
};
|
|
|
|
void *op_mem_stream_create(OpusFileCallbacks *_cb,
|
|
const unsigned char *_data,size_t _size){
|
|
OpusMemStream *stream;
|
|
if(_size>OP_MEM_SIZE_MAX)return NULL;
|
|
stream=(OpusMemStream *)_ogg_malloc(sizeof(*stream));
|
|
if(stream!=NULL){
|
|
*_cb=*&OP_MEM_CALLBACKS;
|
|
stream->data=_data;
|
|
stream->size=_size;
|
|
stream->pos=0;
|
|
}
|
|
return stream;
|
|
}
|