@@ -3136,7 +3136,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
case AVMEDIA_TYPE_DATA:
break;
default:
- abort();
+ av_abort();
break;
}
@@ -1061,7 +1061,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
case AVMEDIA_TYPE_UNKNOWN:
break;
default:
- abort();
+ av_abort();
}
ret = avcodec_parameters_from_context(par, ist->dec_ctx);
@@ -455,7 +455,7 @@ static int find_unused_picture(AVCodecContext *avctx, Picture *picture, int shar
* all. Similarly, missing reference frames have to be replaced by
* interpolated/MC frames, anything else is a bug in the codec ...
*/
- abort();
+ av_abort();
return -1;
}
@@ -62,7 +62,7 @@ static av_always_inline void transform4x4(vec_s16 src_01, vec_s16 src_23,
case 7: add = vec_sl(vec_splat_s32(1), vec_splat_u32( 7 - 1)); break;
case 10: add = vec_sl(vec_splat_s32(1), vec_splat_u32(10 - 1)); break;
case 12: add = vec_sl(vec_splat_s32(1), vec_splat_u32(12 - 1)); break;
- default: abort();
+ default: av_abort();
}
e0 = vec_add(e0, add);
@@ -84,7 +84,7 @@ static av_always_inline void scale(vec_s32 res[4], vec_s16 res_packed[2],
case 7: v_shift = vec_splat_u32(7) ; break;
case 10: v_shift = vec_splat_u32(10); break;
case 12: v_shift = vec_splat_u32(12); break;
- default: abort();
+ default: av_abort();
}
for (i = 0; i < 4; i++)
@@ -63,7 +63,7 @@ static int alloc_table(VLC *vlc, int size, int use_static)
vlc->table_size += size;
if (vlc->table_size > vlc->table_allocated) {
if (use_static)
- abort(); // cannot do anything, init_vlc() is used with too little memory
+ av_abort(); // cannot do anything, init_vlc() is used with too little memory
vlc->table_allocated += (1 << vlc->bits);
vlc->table = av_realloc_f(vlc->table, vlc->table_allocated, sizeof(*vlc->table));
if (!vlc->table) {
@@ -164,7 +164,7 @@ static VP8Frame *vp8_find_free_buffer(VP8Context *s)
}
if (i == 5) {
av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n");
- abort();
+ av_abort();
}
if (frame->tf.f->buf[0])
vp8_release_frame(s, frame);
@@ -107,7 +107,7 @@
* AVFormatContext *s = NULL;
* int ret = avformat_open_input(&s, url, NULL, NULL);
* if (ret < 0)
- * abort();
+ * av_abort();
* @endcode
* The above code attempts to allocate an AVFormatContext, open the
* specified file (autodetecting the format) and read the header, exporting the
@@ -134,7 +134,7 @@
* av_dict_set(&options, "pixel_format", "rgb24", 0);
*
* if (avformat_open_input(&s, url, NULL, &options) < 0)
- * abort();
+ * av_abort();
* av_dict_free(&options);
* @endcode
* This code passes the private options 'video_size' and 'pixel_format' to the
@@ -149,7 +149,7 @@
* AVDictionaryEntry *e;
* if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) {
* fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key);
- * abort();
+ * av_abort();
* }
* @endcode
*
@@ -258,7 +258,7 @@
* AVIODirContext *ctx = NULL;
* if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) {
* fprintf(stderr, "Cannot open directory.\n");
- * abort();
+ * av_abort();
* }
* @endcode
*
@@ -279,7 +279,7 @@
* for (;;) {
* if (avio_read_dir(ctx, &entry) < 0) {
* fprintf(stderr, "Cannot list directory.\n");
- * abort();
+ * av_abort();
* }
* if (!entry)
* break;
@@ -1,7 +1,8 @@
NAME = avutil
DESC = FFmpeg utility library
-HEADERS = adler32.h \
+HEADERS = abort.h \
+ adler32.h \
aes.h \
aes_ctr.h \
attributes.h \
@@ -99,7 +100,8 @@ ARCH_HEADERS = bswap.h \
BUILT_HEADERS = avconfig.h \
ffversion.h
-OBJS = adler32.o \
+OBJS = abort.o \
+ adler32.o \
aes.o \
aes_ctr.o \
audio_fifo.o \
@@ -58,7 +58,7 @@
" -> %016"PRIx64"\n", \
av_bswap64(neon[1][i])); \
} \
- abort(); \
+ av_abort(); \
} \
return ret
new file mode 100644
@@ -0,0 +1,39 @@
+/*
+ * copyright (c) 2022 Genetec inc.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include "abort.h"
+
+void av_abort_default_callback(void)
+{
+ abort();
+}
+
+static void (*av_abort_callback)(void) = av_abort_default_callback;
+
+void av_abort_internal(void)
+{
+ av_abort_callback();
+}
+
+void av_abort_set_callback(void (*callback)(void))
+{
+ av_abort_callback = callback;
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/*
+ * copyright (c) 2022 Genetec inc.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_ABORT_H
+#define AVUTIL_ABORT_H
+
+/**
+ * Causes abnormal program termination. By default, av_abort_callback calls
+ * abort() from the stdlib. This behavior can be altered by setting a
+ * different av_abort callback function.
+ */
+
+void av_abort_internal(void);
+void av_abort_set_callback(void (*)(void));
+void av_abort_default_callback(void);
+
+#define av_abort() do { av_log(NULL, AV_LOG_ERROR, "Abort at %s:%d\n", __FILE__, __LINE__); av_abort_internal(); } while(0)
+
+#endif /* AVUTIL_ABORT_H */
@@ -55,7 +55,7 @@
" -> %016"PRIx64"\n", \
av_bswap64(neon[1][i])); \
} \
- abort(); \
+ av_abort(); \
} \
return ret
@@ -28,6 +28,7 @@
#define AVUTIL_AVASSERT_H
#include <stdlib.h>
+#include "abort.h"
#include "log.h"
#include "macros.h"
@@ -38,7 +39,7 @@
if (!(cond)) { \
av_log(NULL, AV_LOG_PANIC, "Assertion %s failed at %s:%d\n", \
AV_STRINGIFY(cond), __FILE__, __LINE__); \
- abort(); \
+ av_abort_internal(); \
} \
} while (0)
@@ -301,6 +301,7 @@ char av_get_picture_type_char(enum AVPictureType pict_type);
#include "mathematics.h"
#include "log.h"
#include "pixfmt.h"
+#include "abort.h"
/**
* Return x default pointer in case p is NULL.
@@ -41,6 +41,7 @@
#include "attributes.h"
#include "macros.h"
+#include "abort.h"
//rounded division & shift
#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
@@ -173,7 +174,7 @@ av_const int av_log2_16bit(unsigned v);
static av_always_inline av_const int av_clip_c(int a, int amin, int amax)
{
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
if (a < amin) return amin;
else if (a > amax) return amax;
@@ -190,7 +191,7 @@ static av_always_inline av_const int av_clip_c(int a, int amin, int amax)
static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax)
{
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
if (a < amin) return amin;
else if (a > amax) return amax;
@@ -388,7 +389,7 @@ static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) {
static av_always_inline av_const float av_clipf_c(float a, float amin, float amax)
{
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
return FFMIN(FFMAX(a, amin), amax);
}
@@ -405,7 +406,7 @@ static av_always_inline av_const float av_clipf_c(float a, float amin, float ama
static av_always_inline av_const double av_clipd_c(double a, double amin, double amax)
{
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
return FFMIN(FFMAX(a, amin), amax);
}
@@ -38,6 +38,7 @@
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
+#include "abort.h"
#include "config.h"
#include "attributes.h"
#include "timer.h"
@@ -235,7 +236,7 @@ static av_always_inline av_const int64_t ff_rint64_clip(double a, int64_t amin,
{
int64_t res;
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
// INT64_MAX+1,INT64_MIN are exactly representable as IEEE doubles
// do range checks first
@@ -211,7 +211,7 @@ static av_always_inline SoftFloat av_sqrt_sf(SoftFloat val)
if (val.mant == 0)
val.exp = MIN_EXP;
else if (val.mant < 0)
- abort();
+ av_abort();
else
{
tabIndex = (val.mant - 0x20000000) >> 20;
@@ -33,6 +33,7 @@
#include <stdlib.h>
+#include "abort.h"
#include "error.h"
#include "log.h"
#include "macros.h"
@@ -43,7 +44,7 @@
" failed with error: %s\n", \
av_make_error_string(errbuf, AV_ERROR_MAX_STRING_SIZE, \
AVERROR(ret))); \
- abort(); \
+ av_abort_internal(); \
} while (0)
#define ASSERT_PTHREAD_NORET(func, ...) do { \
@@ -20,6 +20,7 @@
#include <stdlib.h>
+#include "abort.h"
#include "config.h"
#include "avassert.h"
#include "avutil.h"
@@ -49,7 +50,7 @@ unsigned avutil_version(void)
if (av_sat_dadd32(1, 2) != 5) {
av_log(NULL, AV_LOG_FATAL, "Libavutil has been built with a broken binutils, please upgrade binutils and rebuild\n");
- abort();
+ av_abort();
}
if (llrint(1LL<<60) != 1LL<<60) {
@@ -30,6 +30,7 @@
#include <immintrin.h>
#endif
#endif
+#include "../abort.h"
#include "config.h"
#if HAVE_FAST_CLZ
@@ -108,7 +109,7 @@ static av_always_inline av_const unsigned av_mod_uintp2_bmi2(unsigned a, unsigne
static av_always_inline av_const double av_clipd_sse2(double a, double amin, double amax)
{
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
__asm__ ("maxsd %1, %0 \n\t"
"minsd %2, %0 \n\t"
@@ -124,7 +125,7 @@ static av_always_inline av_const double av_clipd_sse2(double a, double amin, dou
static av_always_inline av_const float av_clipf_sse(float a, float amin, float amax)
{
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
__asm__ ("maxss %1, %0 \n\t"
"minss %2, %0 \n\t"
@@ -141,7 +142,7 @@ static av_always_inline av_const float av_clipf_sse(float a, float amin, float a
static av_always_inline av_const double av_clipd_avx(double a, double amin, double amax)
{
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
__asm__ ("vmaxsd %1, %0, %0 \n\t"
"vminsd %2, %0, %0 \n\t"
@@ -154,7 +155,7 @@ static av_always_inline av_const double av_clipd_avx(double a, double amin, doub
static av_always_inline av_const float av_clipf_avx(float a, float amin, float amax)
{
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
- if (amin > amax) abort();
+ if (amin > amax) av_abort();
#endif
__asm__ ("vmaxss %1, %0, %0 \n\t"
"vminss %2, %0, %0 \n\t"
@@ -66,7 +66,7 @@
av_bswap64(xmm[1][i][0]), \
av_bswap64(xmm[1][i][1])); \
} \
- abort(); \
+ av_abort(); \
} \
return ret
Replaced all abort() by av_abort() in the code. On production systems, when dealing with malformed data, avcodec was sometime aborting, with no core/memory dump available to troubleshoot after-the-fact. Adding av_abort_set_callback to register a custom function (instead of the default straight abort() behavior), to allow dumping before the actual abort(). Also 'av_logging' the av_abort() location. Signed-off-by: Julien Vary <jvary@genetec.com> --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg_opt.c | 2 +- libavcodec/mpegpicture.c | 2 +- libavcodec/ppc/hevcdsp.c | 4 ++-- libavcodec/vlc.c | 2 +- libavcodec/vp8.c | 2 +- libavformat/avformat.h | 10 ++++----- libavutil/Makefile | 6 ++++-- libavutil/aarch64/neontest.h | 2 +- libavutil/abort.c | 39 ++++++++++++++++++++++++++++++++++++ libavutil/abort.h | 36 +++++++++++++++++++++++++++++++++ libavutil/arm/neontest.h | 2 +- libavutil/avassert.h | 3 ++- libavutil/avutil.h | 1 + libavutil/common.h | 9 +++++---- libavutil/internal.h | 3 ++- libavutil/softfloat.h | 2 +- libavutil/thread.h | 3 ++- libavutil/version.c | 3 ++- libavutil/x86/intmath.h | 9 +++++---- libavutil/x86/w64xmmtest.h | 2 +- 21 files changed, 114 insertions(+), 30 deletions(-) create mode 100644 libavutil/abort.c create mode 100644 libavutil/abort.h