diff --git a/README.md b/README.md index 989628e..28f59b3 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,18 @@ AndroidMagic(使用LibMagic识别文件类型) ================== An android project to query file info with LibMagic +[![Travis](https://img.shields.io/appveyor/ci/gruntjs/grunt.svg)](https://github.com/huzongyao/AndroidMagic/releases) +[![Travis](https://img.shields.io/badge/file-v5.36-brightgreen.svg)](https://github.com/file/file) + +### Introduction +The file command is "a file type guesser", that is, a command-line tool that tells you in words + what kind of data a file contains. Unlike most GUI systems, command-line UNIX systems - with this + program leading the charge - don't rely on filename extentions to tell you the type of a file, + but look at the file's actual contents. This is, of course, more reliable, but requires a bit of I/O. + +### Screenshot +![screenshot](https://github.com/huzongyao/AndroidMagic/blob/master/misc/screen.gif?raw=true) + ### Details This project is for me to learn Java, NDK, and for fun. * learn how to build ndk and sign apk with android gradle-experimental @@ -9,8 +21,9 @@ This project is for me to learn Java, NDK, and for fun. * libmagic is "a file type guesser", that tells you in words what kind of data a file contains ### 学习记录 +* 使用libmagic,我们不用看文件的后缀,就可以识别出常用文件类型 * 移植LibMagic到安卓平台上, 使文件类型的识别不仅通过扩展名 -* 使用gradle-experimental编译NDK +* 使用cmake编译NDK * Java与本地代码之间内存拷贝GetByteArrayRegion * butterknife 以及 rxjava的使用 @@ -18,9 +31,6 @@ This project is for me to learn Java, NDK, and for fun. * Official Site: http://www.darwinsys.com/file/ * GitHub:https://github.com/file/file -### Screenshot -![screenshot](https://github.com/huzongyao/AndroidMagic/blob/master/misc/screen.gif?raw=true) - ### About Me * GitHub: [https://huzongyao.github.io/](https://huzongyao.github.io/) * ITEye博客:[http://hzy3774.iteye.com/](http://hzy3774.iteye.com/) diff --git a/app/build.gradle b/app/build.gradle index fc535ca..f248562 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,8 +1,7 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 27 - buildToolsVersion "27.0.3" + compileSdkVersion 28 signingConfigs { demokey { @@ -15,10 +14,9 @@ android { defaultConfig { applicationId "com.hzy.magic.app" minSdkVersion 15 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 2 - versionName "1.0.1" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + versionName "1.1.1" } compileOptions { targetCompatibility JavaVersion.VERSION_1_8 @@ -35,20 +33,26 @@ android { signingConfig signingConfigs.demokey } } + applicationVariants.all { variant -> + variant.outputs.all { + def fileName = project.name + '-' + variant.name + '-V' + + defaultConfig.versionName + ".apk" + outputFileName = fileName + } + } + lintOptions { + abortOnError false + } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - testImplementation 'junit:junit:4.12' - androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - implementation 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support:cardview-v7:27.1.1' - implementation 'com.android.support:design:27.1.1' - implementation 'com.blankj:utilcode:1.16.1' + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:cardview-v7:28.0.0' + implementation 'com.android.support:design:28.0.0' + implementation 'com.blankj:utilcode:1.23.7' api 'io.reactivex.rxjava2:rxandroid:2.0.2' - api 'com.jakewharton:butterknife:8.8.1' - annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' + api 'com.jakewharton:butterknife:9.0.0' + annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0' implementation project(':libmagic') } diff --git a/app/src/androidTest/java/com/hzy/magic/app/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/hzy/magic/app/ExampleInstrumentedTest.java deleted file mode 100644 index d751092..0000000 --- a/app/src/androidTest/java/com/hzy/magic/app/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.hzy.magic.app; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.hzy.magic.app", appContext.getPackageName()); - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9b1495c..146fb71 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ @@ -10,7 +11,8 @@ android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" - android:theme="@style/AppTheme"> + android:theme="@style/AppTheme" + tools:ignore="GoogleAppIndexingWarning"> diff --git a/app/src/main/java/com/hzy/magic/app/activity/MainActivity.java b/app/src/main/java/com/hzy/magic/app/activity/MainActivity.java index 61caf3e..2de7cf8 100644 --- a/app/src/main/java/com/hzy/magic/app/activity/MainActivity.java +++ b/app/src/main/java/com/hzy/magic/app/activity/MainActivity.java @@ -1,6 +1,6 @@ package com.hzy.magic.app.activity; -import android.Manifest; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.ProgressDialog; import android.os.Build; @@ -15,6 +15,7 @@ import android.view.MenuItem; import android.view.View; +import com.blankj.utilcode.constant.PermissionConstants; import com.blankj.utilcode.util.PermissionUtils; import com.hzy.libmagic.MagicApi; import com.hzy.magic.app.R; @@ -61,7 +62,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); ButterKnife.bind(this); initUI(); - PermissionUtils.permission(Manifest.permission.READ_EXTERNAL_STORAGE) + PermissionUtils.permission(PermissionConstants.STORAGE) .callback(new PermissionUtils.SimpleCallback() { @Override public void onGranted() { @@ -80,12 +81,14 @@ private void initUI() { mProgressDialog.setCancelable(false); mProgressDialog.setTitle("Please Wait..."); mPathList.setAdapter(mPathAdapter = new PathItemAdapter(this, this)); - mPathList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + mPathList.setLayoutManager(new LinearLayoutManager(this, + LinearLayoutManager.HORIZONTAL, false)); mFileList.setAdapter(mFileAdapter = new FileItemAdapter(this, this)); mFileList.setLayoutManager(new LinearLayoutManager(this)); mSwipeRefresh.setOnRefreshListener(this); } + @SuppressLint("CheckResult") private void loadInitPath() { final String path = Environment.getExternalStorageDirectory().getPath(); Observable.create((ObservableOnSubscribe>) e -> { @@ -98,6 +101,7 @@ private void loadInitPath() { .subscribe(this); } + @SuppressLint("CheckResult") private void loadPathInfo(final String path) { Observable.create((ObservableOnSubscribe>) e -> { List infoList = FileUtils.getInfoListFromPath(path); @@ -132,6 +136,11 @@ public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } + @Override + public void onBackPressed() { + super.onBackPressed(); + } + private boolean initMagicFromAssets() { try { InputStream inputStream = getAssets().open("magic.mgc"); @@ -168,7 +177,7 @@ public void onRefresh() { } @Override - public void accept(List fileInfos) throws Exception { + public void accept(List fileInfos) { mFileAdapter.setDataList(fileInfos); mPathAdapter.setPathView(mCurPath); mPathList.scrollToPosition(mPathAdapter.getItemCount() - 1); diff --git a/app/src/main/java/com/hzy/magic/app/adapter/FileItemAdapter.java b/app/src/main/java/com/hzy/magic/app/adapter/FileItemAdapter.java index 89652ef..7196080 100644 --- a/app/src/main/java/com/hzy/magic/app/adapter/FileItemAdapter.java +++ b/app/src/main/java/com/hzy/magic/app/adapter/FileItemAdapter.java @@ -35,7 +35,8 @@ public FileItemAdapter(Activity activity, View.OnClickListener listener) { @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View rootView = LayoutInflater.from(mActivity).inflate(R.layout.storage_list_item, parent, false); + View rootView = LayoutInflater.from(mActivity) + .inflate(R.layout.storage_list_item, parent, false); rootView.setOnClickListener(mItemClickListener); return new ViewHolder(rootView); } diff --git a/app/src/main/java/com/hzy/magic/app/adapter/PathItemAdapter.java b/app/src/main/java/com/hzy/magic/app/adapter/PathItemAdapter.java index bf6ecea..1d45b2d 100644 --- a/app/src/main/java/com/hzy/magic/app/adapter/PathItemAdapter.java +++ b/app/src/main/java/com/hzy/magic/app/adapter/PathItemAdapter.java @@ -1,6 +1,7 @@ package com.hzy.magic.app.adapter; import android.app.Activity; +import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -39,20 +40,21 @@ public void setPathView(String path) { } @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View rootView = LayoutInflater.from(mActivity).inflate(R.layout.path_list_item, parent, false); + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View rootView = LayoutInflater.from(mActivity) + .inflate(R.layout.path_list_item, parent, false); rootView.setOnClickListener(mItemClickListener); return new ViewHolder(rootView); } @Override - public void onBindViewHolder(ViewHolder holder, int position) { + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { String item = mPathStringList[position]; - String curPath = ""; + StringBuilder curPath = new StringBuilder(); for (int i = 0; i < position + 1; i++) { - curPath += mPathStringList[i] + File.separator; + curPath.append(mPathStringList[i]).append(File.separator); } - holder.itemView.setTag(curPath); + holder.itemView.setTag(curPath.toString()); holder.pathText.setText(item); } diff --git a/app/src/test/java/com/hzy/magic/app/ExampleUnitTest.java b/app/src/test/java/com/hzy/magic/app/ExampleUnitTest.java deleted file mode 100644 index 68c7630..0000000 --- a/app/src/test/java/com/hzy/magic/app/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.hzy.magic.app; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 55db43f..ae9fbaf 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.4' + classpath 'com.android.tools.build:gradle:3.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5670ebe..f90d248 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/libmagic/build.gradle b/libmagic/build.gradle index 0aa1625..e713296 100644 --- a/libmagic/build.gradle +++ b/libmagic/build.gradle @@ -1,20 +1,19 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 27 - buildToolsVersion "27.0.3" + compileSdkVersion 28 defaultConfig { minSdkVersion 15 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 2 - versionName "1.1.0" + versionName "1.1.1" ndk { - abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86' + abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86' } externalNativeBuild { cmake { - arguments '-DANDROID_PLATFORM=android-18' + arguments '-DANDROID_PLATFORM=android-21' } } } @@ -36,8 +35,4 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - testImplementation 'junit:junit:4.12' } diff --git a/libmagic/src/androidTest/java/com/hzy/libmagic/ExampleInstrumentedTest.java b/libmagic/src/androidTest/java/com/hzy/libmagic/ExampleInstrumentedTest.java deleted file mode 100644 index cea170f..0000000 --- a/libmagic/src/androidTest/java/com/hzy/libmagic/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.hzy.libmagic; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.hzy.libmagic.test", appContext.getPackageName()); - } -} diff --git a/libmagic/src/main/assets/magic.mgc.gz b/libmagic/src/main/assets/magic.mgc.gz index efbcab0..0699416 100644 Binary files a/libmagic/src/main/assets/magic.mgc.gz and b/libmagic/src/main/assets/magic.mgc.gz differ diff --git a/libmagic/src/main/cpp/file/apprentice.c b/libmagic/src/main/cpp/file/apprentice.c index ea8d0b2..eca3ae0 100644 --- a/libmagic/src/main/cpp/file/apprentice.c +++ b/libmagic/src/main/cpp/file/apprentice.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: apprentice.c,v 1.272 2018/06/22 20:39:50 christos Exp $") +FILE_RCSID("@(#)$File: apprentice.c,v 1.283 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -40,9 +40,7 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.272 2018/06/22 20:39:50 christos Exp $") #ifdef HAVE_UNISTD_H #include #endif -#ifdef HAVE_STDDEF_H #include -#endif #include #include #include @@ -51,20 +49,13 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.272 2018/06/22 20:39:50 christos Exp $") #include #endif #include -#if defined(HAVE_LIMITS_H) #include -#endif -#ifndef SSIZE_MAX -#define MAXMAGIC_SIZE ((ssize_t)0x7fffffff) -#else -#define MAXMAGIC_SIZE SSIZE_MAX -#endif -#define EATAB {while (isascii((unsigned char) *l) && \ - isspace((unsigned char) *l)) ++l;} -#define LOWCASE(l) (isupper((unsigned char) (l)) ? \ - tolower((unsigned char) (l)) : (l)) +#define EATAB {while (isascii(CAST(unsigned char, *l)) && \ + isspace(CAST(unsigned char, *l))) ++l;} +#define LOWCASE(l) (isupper(CAST(unsigned char, l)) ? \ + tolower(CAST(unsigned char, l)) : (l)) /* * Work around a bug in headers on Digital Unix. * At least confirmed for: OSF1 V4.0 878 @@ -83,15 +74,15 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.272 2018/06/22 20:39:50 christos Exp $") #define MAP_FILE 0 #endif -#define ALLOC_CHUNK (size_t)10 -#define ALLOC_INCR (size_t)200 +#define ALLOC_CHUNK CAST(size_t, 10) +#define ALLOC_INCR CAST(size_t, 200) #define MAP_TYPE_USER 0 #define MAP_TYPE_MALLOC 1 #define MAP_TYPE_MMAP 2 struct magic_entry { - struct magic *mp; + struct magic *mp; uint32_t cont_count; uint32_t max_count; }; @@ -126,7 +117,7 @@ private int apprentice_1(struct magic_set *, const char *, int); private size_t apprentice_magic_strength(const struct magic *); private int apprentice_sort(const void *, const void *); private void apprentice_list(struct mlist *, int ); -private struct magic_map *apprentice_load(struct magic_set *, +private struct magic_map *apprentice_load(struct magic_set *, const char *, int); private struct mlist *mlist_alloc(void); private void mlist_free(struct mlist *); @@ -300,12 +291,21 @@ get_type(const struct type_tbl_s *tbl, const char *l, const char **t) return p->type; } +private off_t +maxoff_t(void) { + if (/*CONSTCOND*/sizeof(off_t) == sizeof(int)) + return CAST(off_t, INT_MAX); + if (/*CONSTCOND*/sizeof(off_t) == sizeof(long)) + return CAST(off_t, LONG_MAX); + return 0x7fffffff; +} + private int get_standard_integer_type(const char *l, const char **t) { int type; - if (isalpha((unsigned char)l[1])) { + if (isalpha(CAST(unsigned char, l[1]))) { switch (l[1]) { case 'C': /* "dC" and "uC" */ @@ -340,7 +340,7 @@ get_standard_integer_type(const char *l, const char **t) return FILE_INVALID; } l += 2; - } else if (isdigit((unsigned char)l[1])) { + } else if (isdigit(CAST(unsigned char, l[1]))) { /* * "d{num}" and "u{num}"; we only support {num} values * of 1, 2, 4, and 8 - the Single UNIX Specification @@ -351,7 +351,7 @@ get_standard_integer_type(const char *l, const char **t) * neither of them support values bigger than 8 or * non-power-of-2 values. */ - if (isdigit((unsigned char)l[2])) { + if (isdigit(CAST(unsigned char, l[2]))) { /* Multi-digit, so > 9 */ return FILE_INVALID; } @@ -437,8 +437,8 @@ apprentice_1(struct magic_set *ms, const char *fn, int action) if (magicsize != FILE_MAGICSIZE) { file_error(ms, 0, "magic element size %lu != %lu", - (unsigned long)sizeof(*map->magic[0]), - (unsigned long)FILE_MAGICSIZE); + CAST(unsigned long, sizeof(*map->magic[0])), + CAST(unsigned long, FILE_MAGICSIZE)); return -1; } @@ -451,7 +451,7 @@ apprentice_1(struct magic_set *ms, const char *fn, int action) #ifndef COMPILE_ONLY map = apprentice_map(ms, fn); - if (map == (struct magic_map *)-1) + if (map == RCAST(struct magic_map *, -1)) return -1; if (map == NULL) { if (ms->flags & MAGIC_CHECK) @@ -503,7 +503,7 @@ file_ms_alloc(int flags) struct magic_set *ms; size_t i, len; - if ((ms = CAST(struct magic_set *, calloc((size_t)1, + if ((ms = CAST(struct magic_set *, calloc(CAST(size_t, 1u), sizeof(struct magic_set)))) == NULL) return NULL; @@ -581,6 +581,14 @@ mlist_alloc(void) return mlist; } +private void +mlist_free_one(struct mlist *ml) +{ + if (ml->map) + apprentice_unmap(CAST(struct magic_map *, ml->map)); + free(ml); +} + private void mlist_free(struct mlist *mlist) { @@ -589,14 +597,11 @@ mlist_free(struct mlist *mlist) if (mlist == NULL) return; - ml = mlist->next; - for (ml = mlist->next; (next = ml->next) != NULL; ml = next) { - if (ml->map) - apprentice_unmap(CAST(struct magic_map *, ml->map)); - free(ml); - if (ml == mlist) - break; + for (ml = mlist->next; ml != mlist; ml = next) { + next = ml->next; + mlist_free_one(ml); } + mlist_free_one(mlist); } #ifndef COMPILE_ONLY @@ -826,7 +831,7 @@ typesize(int type) case FILE_LEDOUBLE: return 8; default: - return (size_t)~0; + return CAST(size_t, ~0); } } @@ -836,8 +841,9 @@ typesize(int type) private size_t apprentice_magic_strength(const struct magic *m) { -#define MULT 10 - size_t ts, v, val = 2 * MULT; /* baseline strength */ +#define MULT 10U + size_t ts, v; + ssize_t val = 2 * MULT; /* baseline strength */ switch (m->type) { case FILE_DEFAULT: /* make sure this sorts last */ @@ -880,7 +886,7 @@ apprentice_magic_strength(const struct magic *m) case FILE_BEDOUBLE: case FILE_LEDOUBLE: ts = typesize(m->type); - if (ts == (size_t)~0) + if (ts == CAST(size_t, ~0)) abort(); val += ts * MULT; break; @@ -896,6 +902,8 @@ apprentice_magic_strength(const struct magic *m) break; case FILE_SEARCH: + if (m->vallen == 0) + break; val += m->vallen * MAX(MULT / m->vallen, 1); break; @@ -943,9 +951,6 @@ apprentice_magic_strength(const struct magic *m) abort(); } - if (val == 0) /* ensure we only return 0 for FILE_DEFAULT */ - val = 1; - switch (m->factor_op) { case FILE_FACTOR_OP_NONE: break; @@ -965,6 +970,9 @@ apprentice_magic_strength(const struct magic *m) abort(); } + if (val <= 0) /* ensure we only return 0 for FILE_DEFAULT */ + val = 1; + /* * Magic entries with no description get a bonus because they depend * on subsequent magic entries to print something. @@ -974,7 +982,7 @@ apprentice_magic_strength(const struct magic *m) return val; } -/* +/* * Sort callback for sorting entries by "strength" (basically length) */ private int @@ -992,7 +1000,7 @@ apprentice_sort(const void *a, const void *b) return 1; } -/* +/* * Shows sorted patterns list in the order which is used for the matching */ private void @@ -1088,12 +1096,12 @@ set_test_type(struct magic *mstart, struct magic *m) mstart->flag |= BINTEST; if (mstart->str_flags & STRING_TEXTTEST) mstart->flag |= TEXTTEST; - + if (mstart->flag & (TEXTTEST|BINTEST)) break; /* binary test if pattern is not text */ - if (file_looks_utf8(m->value.us, (size_t)m->vallen, NULL, + if (file_looks_utf8(m->value.us, CAST(size_t, m->vallen), NULL, NULL) <= 0) mstart->flag |= BINTEST; else @@ -1174,7 +1182,7 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs, size_t i; for (i = 0; bang[i].name != NULL; i++) { - if ((size_t)(len - 2) > bang[i].len && + if (CAST(size_t, len - 2) > bang[i].len && memcmp(bang[i].name, line + 2, bang[i].len) == 0) break; @@ -1227,7 +1235,7 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs, private int cmpstrp(const void *p1, const void *p2) { - return strcmp(*(char *const *)p1, *(char *const *)p2); + return strcmp(*RCAST(char *const *, p1), *RCAST(char *const *, p2)); } @@ -1253,10 +1261,10 @@ set_text_binary(struct magic_set *ms, struct magic_entry *me, uint32_t nme, if (me[i].mp->flag & BINTEST) { char *p = strstr(me[i].mp->desc, text); if (p && (p == me[i].mp->desc || - isspace((unsigned char)p[-1])) && + isspace(CAST(unsigned char, p[-1]))) && (p + len - me[i].mp->desc == MAXstring || (p[len] == '\0' || - isspace((unsigned char)p[len])))) + isspace(CAST(unsigned char, p[len]))))) (void)fprintf(stderr, "*** Possible " "binary test for text type\n"); } @@ -1280,7 +1288,7 @@ set_last_default(struct magic_set *ms, struct magic_entry *me, uint32_t nme) file_magwarn(ms, "level 0 \"default\" did not sort last"); } - return; + return; } } } @@ -1387,12 +1395,14 @@ apprentice_load(struct magic_set *ms, const char *fn, int action) filearr[files++] = mfn; } closedir(dir); - qsort(filearr, files, sizeof(*filearr), cmpstrp); - for (i = 0; i < files; i++) { - load_1(ms, action, filearr[i], &errs, mset); - free(filearr[i]); + if (filearr) { + qsort(filearr, files, sizeof(*filearr), cmpstrp); + for (i = 0; i < files; i++) { + load_1(ms, action, filearr[i], &errs, mset); + free(filearr[i]); + } + free(filearr); } - free(filearr); } else load_1(ms, action, fn, &errs, mset); if (errs) @@ -1450,12 +1460,12 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) * the sign extension must have happened. */ case FILE_BYTE: - v = (signed char) v; + v = CAST(signed char, v); break; case FILE_SHORT: case FILE_BESHORT: case FILE_LESHORT: - v = (short) v; + v = CAST(short, v); break; case FILE_DATE: case FILE_BEDATE: @@ -1472,7 +1482,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) case FILE_FLOAT: case FILE_BEFLOAT: case FILE_LEFLOAT: - v = (int32_t) v; + v = CAST(int32_t, v); break; case FILE_QUAD: case FILE_BEQUAD: @@ -1489,7 +1499,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) case FILE_DOUBLE: case FILE_BEDOUBLE: case FILE_LEDOUBLE: - v = (int64_t) v; + v = CAST(int64_t, v); break; case FILE_STRING: case FILE_PSTRING: @@ -1616,7 +1626,7 @@ get_cond(const char *l, const char **t) for (p = cond_tbl; p->len; p++) { if (strncmp(l, p->name, p->len) == 0 && - isspace((unsigned char)l[p->len])) { + isspace(CAST(unsigned char, l[p->len]))) { if (t) *t = l + p->len; break; @@ -1674,7 +1684,7 @@ parse_indirect_modifier(struct magic_set *ms, struct magic *m, const char **lp) { const char *l = *lp; - while (!isspace((unsigned char)*++l)) + while (!isspace(CAST(unsigned char, *++l))) switch (*l) { case CHAR_INDIRECT_RELATIVE: m->str_flags |= INDIRECT_RELATIVE; @@ -1700,7 +1710,7 @@ parse_op_modifier(struct magic_set *ms, struct magic *m, const char **lp, ++l; m->mask_op |= op; - val = (uint64_t)strtoull(l, &t, 0); + val = CAST(uint64_t, strtoull(l, &t, 0)); l = t; m->num_mask = file_signextend(ms, m, val); eatsize(&l); @@ -1714,7 +1724,7 @@ parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp) char *t; int have_range = 0; - while (!isspace((unsigned char)*++l)) { + while (!isspace(CAST(unsigned char, *++l))) { switch (*l) { case '0': case '1': case '2': case '3': case '4': case '5': @@ -1796,7 +1806,7 @@ parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp) goto out; } /* allow multiple '/' for readability */ - if (l[1] == '/' && !isspace((unsigned char)l[2])) + if (l[1] == '/' && !isspace(CAST(unsigned char, l[2]))) l++; } if (string_modifier_check(ms, m) == -1) @@ -1833,7 +1843,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, */ while (*l == '>') { ++l; /* step over */ - cont_level++; + cont_level++; } #ifdef ENABLE_CONDITIONALS if (cont_level == 0 || cont_level > last_cont_level) @@ -1851,7 +1861,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, return -1; } m = &me->mp[me->cont_count - 1]; - diff = (int32_t)cont_level - (int32_t)m->cont_level; + diff = CAST(int32_t, cont_level) - CAST(int32_t, m->cont_level); if (diff > 1) file_magwarn(ms, "New continuation level %u is more " "than one larger than current level %u", cont_level, @@ -1864,7 +1874,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, file_oomem(ms, sizeof(*nm) * cnt); return -1; } - me->mp = m = nm; + me->mp = nm; me->max_count = CAST(uint32_t, cnt); } m = &me->mp[me->cont_count++]; @@ -1910,7 +1920,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, } /* get offset, then skip over it */ - m->offset = (int32_t)strtol(l, &t, 0); + m->offset = CAST(int32_t, strtol(l, &t, 0)); if (l == t) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, "offset `%s' invalid", l); @@ -2008,8 +2018,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, m->in_op |= FILE_OPINDIRECT; l++; } - if (isdigit((unsigned char)*l) || *l == '-') { - m->in_offset = (int32_t)strtol(l, &t, 0); + if (isdigit(CAST(unsigned char, *l)) || *l == '-') { + m->in_offset = CAST(int32_t, strtol(l, &t, 0)); if (l == t) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, @@ -2018,7 +2028,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, } l = t; } - if (*l++ != ')' || + if (*l++ != ')' || ((m->in_op & FILE_OPINDIRECT) && *l++ != ')')) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, @@ -2043,7 +2053,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, /* * Try it as a keyword type prefixed by "u"; match what * follows the "u". If that fails, try it as an SUS - * integer type. + * integer type. */ m->type = get_type(type_tbl, l + 1, &l); if (m->type == FILE_INVALID) { @@ -2072,7 +2082,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, */ if (*l == 'd') m->type = get_standard_integer_type(l, &l); - else if (*l == 's' && !isalpha((unsigned char)l[1])) { + else if (*l == 's' + && !isalpha(CAST(unsigned char, l[1]))) { m->type = FILE_STRING; ++l; } @@ -2083,7 +2094,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, /* Not found - try it as a special keyword. */ m->type = get_type(special_tbl, l, &l); } - + if (m->type == FILE_INVALID) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, "type `%s' invalid", l); @@ -2130,7 +2141,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, * anything if mask = 0 (unless you have a better idea) */ EATAB; - + switch (*l) { case '>': case '<': @@ -2162,8 +2173,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, break; default: m->reln = '='; /* the default relation */ - if (*l == 'x' && ((isascii((unsigned char)l[1]) && - isspace((unsigned char)l[1])) || !l[1])) { + if (*l == 'x' && ((isascii(CAST(unsigned char, l[1])) && + isspace(CAST(unsigned char, l[1]))) || !l[1])) { m->reln = *l; ++l; } @@ -2177,7 +2188,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, /* * TODO finish this macro and start using it! - * #define offsetcheck {if (offset > ms->bytes_max -1) + * #define offsetcheck {if (offset > ms->bytes_max -1) * magwarn("offset too big"); } */ @@ -2260,11 +2271,11 @@ parse_strength(struct magic_set *ms, struct magic_entry *me, const char *line) file_magwarn(ms, "Too large factor `%lu'", factor); goto out; } - if (*el && !isspace((unsigned char)*el)) { + if (*el && !isspace(CAST(unsigned char, *el))) { file_magwarn(ms, "Bad factor `%s'", l); goto out; } - m->factor = (uint8_t)factor; + m->factor = CAST(uint8_t, factor); if (m->factor == 0 && m->factor_op == FILE_FACTOR_OP_DIV) { file_magwarn(ms, "Cannot have factor op `%c' and factor %u", m->factor_op, m->factor); @@ -2295,9 +2306,9 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line, if (buf[0] != '\0') { len = nt ? strlen(buf) : len; file_magwarn(ms, "Current entry already has a %s type " - "`%.*s', new type `%s'", name, (int)len, buf, l); + "`%.*s', new type `%s'", name, CAST(int, len), buf, l); return -1; - } + } if (*m->desc == '\0') { file_magwarn(ms, "Current entry does not yet have a " @@ -2316,7 +2327,7 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line, file_magwarn(ms, "%s type `%s' truncated %" SIZE_T_FORMAT "u", name, line, i); } else { - if (!isspace((unsigned char)*l) && !goodchar(*l, extra)) + if (!isspace(CAST(unsigned char, *l)) && !goodchar(*l, extra)) file_magwarn(ms, "%s type `%s' has bad char '%c'", name, line, *l); if (nt) @@ -2418,7 +2429,7 @@ check_format_type(const char *ptr, int type, const char **estr) if (*ptr == '#') ptr++; #define CHECKLEN() do { \ - for (len = cnt = 0; isdigit((unsigned char)*ptr); ptr++, cnt++) \ + for (len = cnt = 0; isdigit(CAST(unsigned char, *ptr)); ptr++, cnt++) \ len = len * 10 + (*ptr - '0'); \ if (cnt > 5 || len > 1024) \ goto toolong; \ @@ -2434,7 +2445,7 @@ check_format_type(const char *ptr, int type, const char **estr) if (*ptr++ != 'l') goto invalid; } - + switch (*ptr++) { #ifdef STRICT_FORMAT /* "long" formats are int formats for us */ /* so don't accept the 'l' modifier */ @@ -2452,7 +2463,7 @@ check_format_type(const char *ptr, int type, const char **estr) default: goto invalid; } - + /* * Don't accept h and hh modifiers. They make writing * magic entries more complicated, for very little benefit @@ -2508,7 +2519,7 @@ check_format_type(const char *ptr, int type, const char **estr) default: goto invalid; } - + case FILE_FMT_FLOAT: case FILE_FMT_DOUBLE: if (*ptr == '-') @@ -2527,30 +2538,30 @@ check_format_type(const char *ptr, int type, const char **estr) case 'g': case 'G': return 0; - + default: goto invalid; } - + case FILE_FMT_STR: if (*ptr == '-') ptr++; - while (isdigit((unsigned char )*ptr)) + while (isdigit(CAST(unsigned char, *ptr))) ptr++; if (*ptr == '.') { ptr++; - while (isdigit((unsigned char )*ptr)) + while (isdigit(CAST(unsigned char , *ptr))) ptr++; } - + switch (*ptr++) { case 's': return 0; default: goto invalid; } - + default: /* internal error */ abort(); @@ -2561,7 +2572,7 @@ check_format_type(const char *ptr, int type, const char **estr) *estr = "too long"; return -1; } - + /* * Check that the optional printf format in description matches * the type of the magic. @@ -2584,7 +2595,7 @@ check_format(struct magic_set *ms, struct magic *m) if (m->type >= file_nformats) { file_magwarn(ms, "Internal error inconsistency between " - "m->type and format strings"); + "m->type and format strings"); return -1; } if (file_formats[m->type] == FILE_FMT_NONE) { @@ -2604,7 +2615,7 @@ check_format(struct magic_set *ms, struct magic *m) file_names[m->type], m->desc); return -1; } - + for (; *ptr; ptr++) { if (*ptr == '%') { file_magwarn(ms, @@ -2617,9 +2628,9 @@ check_format(struct magic_set *ms, struct magic *m) return 0; } -/* - * Read a numeric value from a pointer, into the value union of a magic - * pointer, according to the magic type. Update the string pointer to point +/* + * Read a numeric value from a pointer, into the value union of a magic + * pointer, according to the magic type. Update the string pointer to point * just after the number read. Return 0 for success, non-zero for failure. */ private int @@ -2685,7 +2696,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action) return 0; default: errno = 0; - ull = (uint64_t)strtoull(*p, &ep, 0); + ull = CAST(uint64_t, strtoull(*p, &ep, 0)); m->value.q = file_signextend(ms, m, ull); if (*p == ep) { file_magwarn(ms, "Unparseable number `%s'", *p); @@ -2694,24 +2705,24 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action) uint64_t x; const char *q; - if (ts == (size_t)~0) { + if (ts == CAST(size_t, ~0)) { file_magwarn(ms, "Expected numeric type got `%s'", type_tbl[m->type].name); } - for (q = *p; isspace((unsigned char)*q); q++) + for (q = *p; isspace(CAST(unsigned char, *q)); q++) continue; if (*q == '-') - ull = -(int64_t)ull; + ull = -CAST(int64_t, ull); switch (ts) { case 1: - x = (uint64_t)(ull & ~0xffULL); + x = CAST(uint64_t, ull & ~0xffULL); break; case 2: - x = (uint64_t)(ull & ~0xffffULL); + x = CAST(uint64_t, ull & ~0xffffULL); break; case 4: - x = (uint64_t)(ull & ~0xffffffffULL); + x = CAST(uint64_t, ull & ~0xffffffffULL); break; case 8: x = 0; @@ -2751,7 +2762,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) int val; while ((c = *s++) != '\0') { - if (isspace((unsigned char) c)) + if (isspace(CAST(unsigned char, c))) break; if (p >= pmax) { file_error(ms, 0, "string too long: `%s'", origs); @@ -2775,8 +2786,8 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) /*FALLTHROUGH*/ default: if (warn) { - if (isprint((unsigned char)c)) { - /* Allow escaping of + if (isprint(CAST(unsigned char, c))) { + /* Allow escaping of * ``relations'' */ if (strchr("<>&^=!", c) == NULL && (m->type != FILE_REGEX || @@ -2813,7 +2824,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) case '!': /* and baskslash itself */ case '\\': - *p++ = (char) c; + *p++ = CAST(char, c); break; case 'a': @@ -2865,7 +2876,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) } else --s; - *p++ = (char)val; + *p++ = CAST(char, val); break; /* \x and up to 2 hex digits */ @@ -2881,18 +2892,18 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) --s; } else --s; - *p++ = (char)val; + *p++ = CAST(char, val); break; } } else - *p++ = (char)c; + *p++ = CAST(char, c); } --s; out: *p = '\0'; m->vallen = CAST(unsigned char, (p - origp)); if (m->type == FILE_PSTRING) - m->vallen += (unsigned char)file_pstring_length_size(m); + m->vallen += CAST(unsigned char, file_pstring_length_size(m)); return s; } @@ -2901,9 +2912,9 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) private int hextoint(int c) { - if (!isascii((unsigned char) c)) + if (!isascii(CAST(unsigned char, c))) return -1; - if (isdigit((unsigned char) c)) + if (isdigit(CAST(unsigned char, c))) return c - '0'; if ((c >= 'a') && (c <= 'f')) return c + 10 - 'a'; @@ -2981,7 +2992,7 @@ eatsize(const char **p) { const char *l = *p; - if (LOWCASE(*l) == 'u') + if (LOWCASE(*l) == 'u') l++; switch (LOWCASE(*l)) { @@ -3052,17 +3063,17 @@ apprentice_map(struct magic_set *ms, const char *fn) file_error(ms, errno, "cannot stat `%s'", dbname); goto error; } - if (st.st_size < 8 || st.st_size > MAXMAGIC_SIZE) { + if (st.st_size < 8 || st.st_size > maxoff_t()) { file_error(ms, 0, "file `%s' is too %s", dbname, st.st_size < 8 ? "small" : "large"); goto error; } - map->len = (size_t)st.st_size; + map->len = CAST(size_t, st.st_size); #ifdef QUICK map->type = MAP_TYPE_MMAP; - if ((map->p = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) { + if ((map->p = mmap(0, CAST(size_t, st.st_size), PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_FILE, fd, CAST(off_t, 0))) == MAP_FAILED) { file_error(ms, errno, "cannot map `%s'", dbname); goto error; } @@ -3082,11 +3093,11 @@ apprentice_map(struct magic_set *ms, const char *fn) fd = -1; if (check_buffer(ms, map, dbname) != 0) { - rv = (struct magic_map *)-1; + rv = RCAST(struct magic_map *, -1); goto error; } #ifdef QUICK - if (mprotect(map->p, (size_t)st.st_size, PROT_READ) == -1) { + if (mprotect(map->p, CAST(size_t, st.st_size), PROT_READ) == -1) { file_error(ms, errno, "cannot mprotect `%s'", dbname); goto error; } @@ -3130,7 +3141,7 @@ check_buffer(struct magic_set *ms, struct magic_map *map, const char *dbname) VERSIONNO, dbname, version); return -1; } - entries = (uint32_t)(map->len / sizeof(struct magic)); + entries = CAST(uint32_t, map->len / sizeof(struct magic)); if ((entries * sizeof(struct magic)) != map->len) { file_error(ms, 0, "Size of `%s' %" SIZE_T_FORMAT "u is not " "a multiple of %" SIZE_T_FORMAT "u", @@ -3179,10 +3190,10 @@ apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn) dbname = mkdbname(ms, fn, 1); - if (dbname == NULL) + if (dbname == NULL) goto out; - if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) + if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) { file_error(ms, errno, "cannot open `%s'", dbname); goto out; @@ -3192,14 +3203,14 @@ apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn) hdr.h[1] = VERSIONNO; memcpy(hdr.h + 2, map->nmagic, nm); - if (write(fd, &hdr, sizeof(hdr)) != (ssize_t)sizeof(hdr)) { + if (write(fd, &hdr, sizeof(hdr)) != CAST(ssize_t, sizeof(hdr))) { file_error(ms, errno, "error writing `%s'", dbname); goto out2; } for (i = 0; i < MAGIC_SETS; i++) { len = m * map->nmagic[i]; - if (write(fd, map->magic[i], len) != (ssize_t)len) { + if (write(fd, map->magic[i], len) != CAST(ssize_t, len)) { file_error(ms, errno, "error writing `%s'", dbname); goto out2; } @@ -3245,7 +3256,8 @@ mkdbname(struct magic_set *ms, const char *fn, int strip) q++; /* Compatibility with old code that looked in .mime */ if (ms->flags & MAGIC_MIME) { - if (asprintf(&buf, "%.*s.mime%s", (int)(q - fn), fn, ext) < 0) + if (asprintf(&buf, "%.*s.mime%s", CAST(int, q - fn), fn, ext) + < 0) return NULL; if (access(buf, R_OK) != -1) { ms->flags &= MAGIC_MIME_TYPE; @@ -3253,7 +3265,7 @@ mkdbname(struct magic_set *ms, const char *fn, int strip) } free(buf); } - if (asprintf(&buf, "%.*s%s", (int)(q - fn), fn, ext) < 0) + if (asprintf(&buf, "%.*s%s", CAST(int, q - fn), fn, ext) < 0) return NULL; /* Compatibility with old code that looked in .mime */ @@ -3280,8 +3292,8 @@ private uint16_t swap2(uint16_t sv) { uint16_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[1]; d[1] = s[0]; return rv; @@ -3294,8 +3306,8 @@ private uint32_t swap4(uint32_t sv) { uint32_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; @@ -3310,8 +3322,8 @@ private uint64_t swap8(uint64_t sv) { uint64_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); #if 0 d[0] = s[3]; d[1] = s[2]; @@ -3341,9 +3353,9 @@ private void bs1(struct magic *m) { m->cont_level = swap2(m->cont_level); - m->offset = swap4((uint32_t)m->offset); - m->in_offset = swap4((uint32_t)m->in_offset); - m->lineno = swap4((uint32_t)m->lineno); + m->offset = swap4(CAST(uint32_t, m->offset)); + m->in_offset = swap4(CAST(uint32_t, m->in_offset)); + m->lineno = swap4(CAST(uint32_t, m->lineno)); if (IS_STRING(m->type)) { m->str_range = swap4(m->str_range); m->str_flags = swap4(m->str_flags); @@ -3354,7 +3366,7 @@ bs1(struct magic *m) } } -protected size_t +protected size_t file_pstring_length_size(const struct magic *m) { switch (m->str_flags & PSTRING_LEN) { @@ -3375,7 +3387,7 @@ protected size_t file_pstring_get_length(const struct magic *m, const char *ss) { size_t len = 0; - const unsigned char *s = (const unsigned char *)ss; + const unsigned char *s = RCAST(const unsigned char *, ss); unsigned int s3, s2, s1, s0; switch (m->str_flags & PSTRING_LEN) { diff --git a/libmagic/src/main/cpp/file/apptype.c b/libmagic/src/main/cpp/file/apptype.c index 164c4f3..1bb33e4 100644 --- a/libmagic/src/main/cpp/file/apptype.c +++ b/libmagic/src/main/cpp/file/apptype.c @@ -1,15 +1,15 @@ /* * Adapted from: apptype.c, Written by Eberhard Mattes and put into the * public domain - * + * * Notes: 1. Qualify the filename so that DosQueryAppType does not do extraneous * searches. - * + * * 2. DosQueryAppType will return FAPPTYP_DOS on a file ending with ".com" * (other than an OS/2 exe or Win exe with this name). Eberhard Mattes * remarks Tue, 6 Apr 93: Moreover, it reports the type of the (new and very * bug ridden) Win Emacs as "OS/2 executable". - * + * * 3. apptype() uses the filename if given, otherwise a tmp file is created with * the contents of buf. If buf is not the complete file, apptype can * incorrectly identify the exe type. The "-z" option of "file" is the reason @@ -18,16 +18,16 @@ /* * amai: Darrel Hankerson did the changes described here. - * + * * It remains to check the validity of comments (2.) since it's referred to an * "old" OS/2 version. - * + * */ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: apptype.c,v 1.12 2011/08/28 07:03:27 christos Exp $") +FILE_RCSID("@(#)$File: apptype.c,v 1.14 2018/09/09 20:33:28 christos Exp $") #endif /* lint */ #include diff --git a/libmagic/src/main/cpp/file/ascmagic.c b/libmagic/src/main/cpp/file/ascmagic.c index 2d1abe5..bcebeab 100644 --- a/libmagic/src/main/cpp/file/ascmagic.c +++ b/libmagic/src/main/cpp/file/ascmagic.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: ascmagic.c,v 1.98 2017/11/02 20:25:39 christos Exp $") +FILE_RCSID("@(#)$File: ascmagic.c,v 1.102 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -80,7 +80,13 @@ file_ascmagic(struct magic_set *ms, const struct buffer *b, int text) const char *type = NULL; bb = *b; - bb.flen = trim_nuls(b->fbuf, b->flen); + bb.flen = trim_nuls(CAST(const unsigned char *, b->fbuf), b->flen); + /* + * Avoid trimming at an odd byte if the original buffer was evenly + * sized; this avoids losing the last character on UTF-16 LE text + */ + if ((bb.flen & 1) && !(b->flen & 1)) + bb.flen++; /* If file doesn't look like any sort of text, give up. */ if (file_encoding(ms, &bb, &ubuf, &ulen, &code, &code_mime, @@ -96,12 +102,12 @@ file_ascmagic(struct magic_set *ms, const struct buffer *b, int text) } protected int -file_ascmagic_with_encoding(struct magic_set *ms, +file_ascmagic_with_encoding(struct magic_set *ms, const struct buffer *b, unichar *ubuf, size_t ulen, const char *code, const char *type, int text) { struct buffer bb; - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; unsigned char *utf8_buf = NULL, *utf8_end; size_t mlen, i; @@ -121,7 +127,7 @@ file_ascmagic_with_encoding(struct magic_set *ms, int n_nel = 0; int executable = 0; - size_t last_line_end = (size_t)-1; + size_t last_line_end = CAST(size_t, -1); int has_long_lines = 0; nbytes = trim_nuls(buf, nbytes); @@ -145,7 +151,7 @@ file_ascmagic_with_encoding(struct magic_set *ms, == NULL) goto done; buffer_init(&bb, b->fd, utf8_buf, - (size_t)(utf8_end - utf8_buf)); + CAST(size_t, utf8_end - utf8_buf)); if ((rv = file_softmagic(ms, &bb, NULL, NULL, TEXTTEST, text)) == 0) @@ -324,42 +330,42 @@ encode_utf8(unsigned char *buf, size_t len, unichar *ubuf, size_t ulen) if (ubuf[i] <= 0x7f) { if (end - buf < 1) return NULL; - *buf++ = (unsigned char)ubuf[i]; + *buf++ = CAST(unsigned char, ubuf[i]); } else if (ubuf[i] <= 0x7ff) { if (end - buf < 2) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 6) + 0xc0); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 6) + 0xc0); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else if (ubuf[i] <= 0xffff) { if (end - buf < 3) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 12) + 0xe0); - *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 12) + 0xe0); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else if (ubuf[i] <= 0x1fffff) { if (end - buf < 4) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 18) + 0xf0); - *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 18) + 0xf0); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else if (ubuf[i] <= 0x3ffffff) { if (end - buf < 5) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 24) + 0xf8); - *buf++ = (unsigned char)(((ubuf[i] >> 18) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 24) + 0xf8); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 18) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else if (ubuf[i] <= 0x7fffffff) { if (end - buf < 6) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 30) + 0xfc); - *buf++ = (unsigned char)(((ubuf[i] >> 24) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 18) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 30) + 0xfc); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 24) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 18) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else /* Invalid character */ return NULL; } diff --git a/libmagic/src/main/cpp/file/asprintf.c b/libmagic/src/main/cpp/file/asprintf.c index b065380..2d14e80 100644 --- a/libmagic/src/main/cpp/file/asprintf.c +++ b/libmagic/src/main/cpp/file/asprintf.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -29,7 +29,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: asprintf.c,v 1.3 2009/02/03 20:27:51 christos Exp $") +FILE_RCSID("@(#)$File: asprintf.c,v 1.5 2018/09/09 20:33:28 christos Exp $") #endif int asprintf(char **ptr, const char *fmt, ...) diff --git a/libmagic/src/main/cpp/file/buffer.c b/libmagic/src/main/cpp/file/buffer.c index 5f76b80..fd40416 100644 --- a/libmagic/src/main/cpp/file/buffer.c +++ b/libmagic/src/main/cpp/file/buffer.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: buffer.c,v 1.4 2018/02/21 21:26:00 christos Exp $") +FILE_RCSID("@(#)$File: buffer.c,v 1.5 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -61,13 +61,13 @@ buffer_fill(const struct buffer *bb) struct buffer *b = CCAST(struct buffer *, bb); if (b->elen != 0) - return b->elen == (size_t)~0 ? -1 : 0; + return b->elen == CAST(size_t, ~0) ? -1 : 0; if (!S_ISREG(b->st.st_mode)) goto out; - b->elen = (size_t)b->st.st_size < b->flen ? - (size_t)b->st.st_size : b->flen; + b->elen = CAST(size_t, b->st.st_size) < b->flen ? + CAST(size_t, b->st.st_size) : b->flen; if ((b->ebuf = malloc(b->elen)) == NULL) goto out; @@ -79,6 +79,6 @@ buffer_fill(const struct buffer *bb) return 0; out: - b->elen = (size_t)~0; + b->elen = CAST(size_t, ~0); return -1; } diff --git a/libmagic/src/main/cpp/file/cdf.c b/libmagic/src/main/cpp/file/cdf.c index aad68cd..556a3ff 100644 --- a/libmagic/src/main/cpp/file/cdf.c +++ b/libmagic/src/main/cpp/file/cdf.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: cdf.c,v 1.110 2017/12/19 00:21:21 christos Exp $") +FILE_RCSID("@(#)$File: cdf.c,v 1.114 2019/02/20 02:35:27 christos Exp $") #endif #include @@ -47,9 +47,7 @@ FILE_RCSID("@(#)$File: cdf.c,v 1.110 2017/12/19 00:21:21 christos Exp $") #include #include #include -#ifdef HAVE_LIMITS_H #include -#endif #ifndef EFTYPE #define EFTYPE EINVAL @@ -68,11 +66,14 @@ static union { uint32_t u; } cdf_bo; -#define NEED_SWAP (cdf_bo.u == (uint32_t)0x01020304) +#define NEED_SWAP (cdf_bo.u == CAST(uint32_t, 0x01020304)) -#define CDF_TOLE8(x) ((uint64_t)(NEED_SWAP ? _cdf_tole8(x) : (uint64_t)(x))) -#define CDF_TOLE4(x) ((uint32_t)(NEED_SWAP ? _cdf_tole4(x) : (uint32_t)(x))) -#define CDF_TOLE2(x) ((uint16_t)(NEED_SWAP ? _cdf_tole2(x) : (uint16_t)(x))) +#define CDF_TOLE8(x) \ + (CAST(uint64_t, NEED_SWAP ? _cdf_tole8(x) : CAST(uint64_t, x))) +#define CDF_TOLE4(x) \ + (CAST(uint32_t, NEED_SWAP ? _cdf_tole4(x) : CAST(uint32_t, x))) +#define CDF_TOLE2(x) \ + (CAST(uint16_t, NEED_SWAP ? _cdf_tole2(x) : CAST(uint16_t, x))) #define CDF_TOLE(x) (/*CONSTCOND*/sizeof(x) == 2 ? \ CDF_TOLE2(CAST(uint16_t, x)) : \ (/*CONSTCOND*/sizeof(x) == 4 ? \ @@ -90,7 +91,8 @@ static void * cdf_malloc(const char *file __attribute__((__unused__)), size_t line __attribute__((__unused__)), size_t n) { - DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n)); + DPRINTF(("%s,%" SIZE_T_FORMAT "u: %s %" SIZE_T_FORMAT "u\n", + file, line, __func__, n)); return malloc(n); } @@ -99,7 +101,8 @@ static void * cdf_realloc(const char *file __attribute__((__unused__)), size_t line __attribute__((__unused__)), void *p, size_t n) { - DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n)); + DPRINTF(("%s,%" SIZE_T_FORMAT "u: %s %" SIZE_T_FORMAT "u\n", + file, line, __func__, n)); return realloc(p, n); } @@ -108,7 +111,8 @@ static void * cdf_calloc(const char *file __attribute__((__unused__)), size_t line __attribute__((__unused__)), size_t n, size_t u) { - DPRINTF(("%s,%zu: %s %zu %zu\n", file, line, __func__, n, u)); + DPRINTF(("%s,%" SIZE_T_FORMAT "u: %s %" SIZE_T_FORMAT "u %" + SIZE_T_FORMAT "u\n", file, line, __func__, n, u)); return calloc(n, u); } @@ -119,8 +123,8 @@ static uint16_t _cdf_tole2(uint16_t sv) { uint16_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[1]; d[1] = s[0]; return rv; @@ -133,8 +137,8 @@ static uint32_t _cdf_tole4(uint32_t sv) { uint32_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; @@ -149,8 +153,8 @@ static uint64_t _cdf_tole8(uint64_t sv) { uint64_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[7]; d[1] = s[6]; d[2] = s[5]; @@ -215,15 +219,17 @@ cdf_swap_header(cdf_header_t *h) h->h_min_size_standard_stream = CDF_TOLE4(h->h_min_size_standard_stream); h->h_secid_first_sector_in_short_sat = - CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_short_sat); + CDF_TOLE4(CAST(uint32_t, h->h_secid_first_sector_in_short_sat)); h->h_num_sectors_in_short_sat = CDF_TOLE4(h->h_num_sectors_in_short_sat); h->h_secid_first_sector_in_master_sat = - CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_master_sat); + CDF_TOLE4(CAST(uint32_t, h->h_secid_first_sector_in_master_sat)); h->h_num_sectors_in_master_sat = CDF_TOLE4(h->h_num_sectors_in_master_sat); - for (i = 0; i < __arraycount(h->h_master_sat); i++) - h->h_master_sat[i] = CDF_TOLE4((uint32_t)h->h_master_sat[i]); + for (i = 0; i < __arraycount(h->h_master_sat); i++) { + h->h_master_sat[i] = + CDF_TOLE4(CAST(uint32_t, h->h_master_sat[i])); + } } void @@ -256,15 +262,16 @@ void cdf_swap_dir(cdf_directory_t *d) { d->d_namelen = CDF_TOLE2(d->d_namelen); - d->d_left_child = CDF_TOLE4((uint32_t)d->d_left_child); - d->d_right_child = CDF_TOLE4((uint32_t)d->d_right_child); - d->d_storage = CDF_TOLE4((uint32_t)d->d_storage); + d->d_left_child = CDF_TOLE4(CAST(uint32_t, d->d_left_child)); + d->d_right_child = CDF_TOLE4(CAST(uint32_t, d->d_right_child)); + d->d_storage = CDF_TOLE4(CAST(uint32_t, d->d_storage)); d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]); d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]); d->d_flags = CDF_TOLE4(d->d_flags); - d->d_created = CDF_TOLE8((uint64_t)d->d_created); - d->d_modified = CDF_TOLE8((uint64_t)d->d_modified); - d->d_stream_first_sector = CDF_TOLE4((uint32_t)d->d_stream_first_sector); + d->d_created = CDF_TOLE8(CAST(uint64_t, d->d_created)); + d->d_modified = CDF_TOLE8(CAST(uint64_t, d->d_modified)); + d->d_stream_first_sector = CDF_TOLE4( + CAST(uint32_t, d->d_stream_first_sector)); d->d_size = CDF_TOLE4(d->d_size); } @@ -321,11 +328,11 @@ static int cdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h, const void *p, size_t tail, int line) { - const char *b = (const char *)sst->sst_tab; - const char *e = ((const char *)p) + tail; + const char *b = RCAST(const char *, sst->sst_tab); + const char *e = RCAST(const char *, p) + tail; size_t ss = cdf_check_stream(sst, h); /*LINTED*/(void)&line; - if (e >= b && (size_t)(e - b) <= ss * sst->sst_len) + if (e >= b && CAST(size_t, e - b) <= ss * sst->sst_len) return 0; DPRINTF(("%d: offset begin %p < end %p || %" SIZE_T_FORMAT "u" " > %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %" @@ -338,23 +345,23 @@ cdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h, static ssize_t cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len) { - size_t siz = (size_t)off + len; + size_t siz = CAST(size_t, off + len); - if ((off_t)(off + len) != (off_t)siz) + if (CAST(off_t, off + len) != CAST(off_t, siz)) goto out; if (info->i_buf != NULL && info->i_len >= siz) { (void)memcpy(buf, &info->i_buf[off], len); - return (ssize_t)len; + return CAST(ssize_t, len); } if (info->i_fd == -1) goto out; - if (pread(info->i_fd, buf, len, off) != (ssize_t)len) + if (pread(info->i_fd, buf, len, off) != CAST(ssize_t, len)) return -1; - return (ssize_t)len; + return CAST(ssize_t, len); out: errno = EINVAL; return -1; @@ -366,7 +373,7 @@ cdf_read_header(const cdf_info_t *info, cdf_header_t *h) char buf[512]; (void)memcpy(cdf_bo.s, "\01\02\03\04", 4); - if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1) + if (cdf_read(info, CAST(off_t, 0), buf, sizeof(buf)) == -1) return -1; cdf_unpack_header(h, buf); cdf_swap_header(h); @@ -400,7 +407,7 @@ cdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len, size_t ss = CDF_SEC_SIZE(h); size_t pos = CDF_SEC_POS(h, id); assert(ss == len); - return cdf_read(info, (off_t)pos, ((char *)buf) + offs, len); + return cdf_read(info, CAST(off_t, pos), RCAST(char *, buf) + offs, len); } ssize_t @@ -416,8 +423,8 @@ cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, pos + len, CDF_SEC_SIZE(h) * sst->sst_len)); goto out; } - (void)memcpy(((char *)buf) + offs, - ((const char *)sst->sst_tab) + pos, len); + (void)memcpy(RCAST(char *, buf) + offs, + RCAST(const char *, sst->sst_tab) + pos, len); return len; out: errno = EFTYPE; @@ -460,7 +467,7 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) if (h->h_master_sat[i] < 0) break; if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, - h->h_master_sat[i]) != (ssize_t)ss) { + h->h_master_sat[i]) != CAST(ssize_t, ss)) { DPRINTF(("Reading sector %d", h->h_master_sat[i])); goto out1; } @@ -477,27 +484,29 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) DPRINTF(("Reading master sector loop limit")); goto out3; } - if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) { + if (cdf_read_sector(info, msa, 0, ss, h, mid) != + CAST(ssize_t, ss)) { DPRINTF(("Reading master sector %d", mid)); goto out2; } for (k = 0; k < nsatpersec; k++, i++) { - sec = CDF_TOLE4((uint32_t)msa[k]); + sec = CDF_TOLE4(CAST(uint32_t, msa[k])); if (sec < 0) goto out; if (i >= sat->sat_len) { - DPRINTF(("Out of bounds reading MSA %" SIZE_T_FORMAT - "u >= %" SIZE_T_FORMAT "u", i, sat->sat_len)); + DPRINTF(("Out of bounds reading MSA %" + SIZE_T_FORMAT "u >= %" SIZE_T_FORMAT "u", + i, sat->sat_len)); goto out3; } if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, - sec) != (ssize_t)ss) { + sec) != CAST(ssize_t, ss)) { DPRINTF(("Reading sector %d", CDF_TOLE4(msa[k]))); goto out2; } } - mid = CDF_TOLE4((uint32_t)msa[nsatpersec]); + mid = CDF_TOLE4(CAST(uint32_t, msa[nsatpersec])); } out: sat->sat_len = i; @@ -516,7 +525,7 @@ size_t cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) { size_t i, j; - cdf_secid_t maxsector = (cdf_secid_t)((sat->sat_len * size) + cdf_secid_t maxsector = CAST(cdf_secid_t, (sat->sat_len * size) / sizeof(maxsector)); DPRINTF(("Chain:")); @@ -536,7 +545,7 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) DPRINTF(("Sector %d >= %d\n", sid, maxsector)); goto out; } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid])); } if (i == 0) { DPRINTF((" none, sid: %d\n", sid)); @@ -547,7 +556,7 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) return i; out: errno = EFTYPE; - return (size_t)-1; + return CAST(size_t, -1); } int @@ -564,7 +573,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, if (sid == CDF_SECID_END_OF_CHAIN || len == 0) return cdf_zero_stream(scn); - if (scn->sst_len == (size_t)-1) + if (scn->sst_len == CAST(size_t, -1)) goto out; scn->sst_tab = CDF_CALLOC(scn->sst_len, ss); @@ -583,7 +592,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, goto out; } if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h, - sid)) != (ssize_t)ss) { + sid)) != CAST(ssize_t, ss)) { if (i == scn->sst_len - 1 && nr > 0) { /* Last sector might be truncated */ return 0; @@ -591,7 +600,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, DPRINTF(("Reading long sector chain %d", sid)); goto out; } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid])); } return 0; out: @@ -610,7 +619,7 @@ cdf_read_short_sector_chain(const cdf_header_t *h, scn->sst_dirlen = len; scn->sst_ss = ss; - if (scn->sst_len == (size_t)-1) + if (scn->sst_len == CAST(size_t, -1)) goto out; scn->sst_tab = CDF_CALLOC(scn->sst_len, ss); @@ -629,11 +638,11 @@ cdf_read_short_sector_chain(const cdf_header_t *h, goto out; } if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h, - sid) != (ssize_t)ss) { + sid) != CAST(ssize_t, ss)) { DPRINTF(("Reading short sector chain %d", sid)); goto out; } - sid = CDF_TOLE4((uint32_t)ssat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, ssat->sat_tab[sid])); } return 0; out: @@ -664,7 +673,7 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, cdf_secid_t sid = h->h_secid_first_directory; ns = cdf_count_chain(sat, sid, ss); - if (ns == (size_t)-1) + if (ns == CAST(size_t, -1)) return -1; nd = ss / CDF_DIRECTORY_SIZE; @@ -685,7 +694,8 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, DPRINTF(("Read dir loop limit")); goto out; } - if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) { + if (cdf_read_sector(info, buf, 0, ss, h, sid) != + CAST(ssize_t, ss)) { DPRINTF(("Reading directory sector %d", sid)); goto out; } @@ -693,7 +703,7 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, cdf_unpack_dir(&dir->dir_tab[i * nd + j], &buf[j * CDF_DIRECTORY_SIZE]); } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid])); } if (NEED_SWAP) for (i = 0; i < dir->dir_len; i++) @@ -718,7 +728,7 @@ cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, ssat->sat_tab = NULL; ssat->sat_len = cdf_count_chain(sat, sid, ss); - if (ssat->sat_len == (size_t)-1) + if (ssat->sat_len == CAST(size_t, -1)) goto out; ssat->sat_tab = CAST(cdf_secid_t *, CDF_CALLOC(ssat->sat_len, ss)); @@ -737,11 +747,11 @@ cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, goto out; } if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) != - (ssize_t)ss) { + CAST(ssize_t, ss)) { DPRINTF(("Reading short sat sector %d", sid)); goto out1; } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid])); } return 0; out: @@ -791,7 +801,7 @@ cdf_namecmp(const char *d, const uint16_t *s, size_t l) { for (; l--; d++, s++) if (*d != CDF_TOLE2(*s)) - return (unsigned char)*d - CDF_TOLE2(*s); + return CAST(unsigned char, *d) - CDF_TOLE2(*s); return 0; } @@ -859,7 +869,7 @@ cdf_offset(const void *p, size_t l) } static const uint8_t * -cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, +cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, const uint8_t *p, const uint8_t *e, size_t i) { size_t tail = (i << 1) + 1; @@ -874,7 +884,7 @@ cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, __LINE__) == -1) return NULL; ofs = CDF_GETUINT32(p, tail); - q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p), + q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p), ofs - 2 * sizeof(uint32_t))); if (q < p) { @@ -896,8 +906,8 @@ cdf_grow_info(cdf_property_info_t **info, size_t *maxcount, size_t incr) size_t newcount = *maxcount + incr; if (newcount > CDF_PROP_LIMIT) { - DPRINTF(("exceeded property limit %zu > %zu\n", - newcount, CDF_PROP_LIMIT)); + DPRINTF(("exceeded property limit %" SIZE_T_FORMAT "u > %" + SIZE_T_FORMAT "u\n", newcount, CDF_PROP_LIMIT)); goto out; } inp = CAST(cdf_property_info_t *, @@ -922,7 +932,7 @@ cdf_copy_info(cdf_property_info_t *inp, const void *p, const void *e, if (inp->pi_type & CDF_VECTOR) return 0; - if ((size_t)(CAST(const char *, e) - CAST(const char *, p)) < len) + if (CAST(size_t, CAST(const char *, e) - CAST(const char *, p)) < len) return 0; (void)memcpy(&inp->pi_val, p, len); @@ -1065,10 +1075,10 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, inp[i].pi_str.s_buf = CAST(const char *, CAST(const void *, &q[o4])); - DPRINTF(("o=%zu l=%d(%" SIZE_T_FORMAT - "u), t=%zu s=%s\n", o4, l, - CDF_ROUND(l, sizeof(l)), left, - inp[i].pi_str.s_buf)); + DPRINTF(("o=%" SIZE_T_FORMAT "u l=%d(%" + SIZE_T_FORMAT "u), t=%" SIZE_T_FORMAT + "u s=%s\n", o4, l, CDF_ROUND(l, sizeof(l)), + left, inp[i].pi_str.s_buf)); if (l & 1) l++; @@ -1108,8 +1118,9 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h, const cdf_summary_info_header_t *si = CAST(const cdf_summary_info_header_t *, sst->sst_tab); const cdf_section_declaration_t *sd = - CAST(const cdf_section_declaration_t *, (const void *) - ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET)); + CAST(const cdf_section_declaration_t *, RCAST(const void *, + RCAST(const char *, sst->sst_tab) + + CDF_SECTION_DECLARATION_OFFSET)); if (cdf_check_stream_offset(sst, h, si, sizeof(*si), __LINE__) == -1 || cdf_check_stream_offset(sst, h, sd, sizeof(*sd), __LINE__) == -1) @@ -1260,28 +1271,28 @@ cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts) int days, hours, mins, secs; ts /= CDF_TIME_PREC; - secs = (int)(ts % 60); + secs = CAST(int, ts % 60); ts /= 60; - mins = (int)(ts % 60); + mins = CAST(int, ts % 60); ts /= 60; - hours = (int)(ts % 24); + hours = CAST(int, ts % 24); ts /= 24; - days = (int)ts; + days = CAST(int, ts); if (days) { len += snprintf(buf + len, bufsiz - len, "%dd+", days); - if ((size_t)len >= bufsiz) + if (CAST(size_t, len) >= bufsiz) return len; } if (days || hours) { len += snprintf(buf + len, bufsiz - len, "%.2d:", hours); - if ((size_t)len >= bufsiz) + if (CAST(size_t, len) >= bufsiz) return len; } len += snprintf(buf + len, bufsiz - len, "%.2d:", mins); - if ((size_t)len >= bufsiz) + if (CAST(size_t, len) >= bufsiz) return len; len += snprintf(buf + len, bufsiz - len, "%.2d", secs); @@ -1293,7 +1304,7 @@ cdf_u16tos8(char *buf, size_t len, const uint16_t *p) { size_t i; for (i = 0; i < len && p[i]; i++) - buf[i] = (char)p[i]; + buf[i] = CAST(char, p[i]); buf[i] = '\0'; return buf; } diff --git a/libmagic/src/main/cpp/file/cdf.h b/libmagic/src/main/cpp/file/cdf.h index f2df830..2f7e554 100644 --- a/libmagic/src/main/cpp/file/cdf.h +++ b/libmagic/src/main/cpp/file/cdf.h @@ -76,9 +76,9 @@ typedef struct { cdf_secid_t h_master_sat[436/4]; } cdf_header_t; -#define CDF_SEC_SIZE(h) ((size_t)(1 << (h)->h_sec_size_p2)) +#define CDF_SEC_SIZE(h) CAST(size_t, 1 << (h)->h_sec_size_p2) #define CDF_SEC_POS(h, secid) (CDF_SEC_SIZE(h) + (secid) * CDF_SEC_SIZE(h)) -#define CDF_SHORT_SEC_SIZE(h) ((size_t)(1 << (h)->h_short_sec_size_p2)) +#define CDF_SHORT_SEC_SIZE(h) CAST(size_t, 1 << (h)->h_short_sec_size_p2) #define CDF_SHORT_SEC_POS(h, secid) ((secid) * CDF_SHORT_SEC_SIZE(h)) typedef int32_t cdf_dirid_t; @@ -272,7 +272,7 @@ typedef struct { typedef struct { uint16_t ce_namlen; uint32_t ce_num; - uint64_t ce_timestamp; + uint64_t ce_timestamp; uint16_t ce_name[256]; } cdf_catalog_entry_t; diff --git a/libmagic/src/main/cpp/file/cdf_time.c b/libmagic/src/main/cpp/file/cdf_time.c index 2bdcd2a..bdb2d3a 100644 --- a/libmagic/src/main/cpp/file/cdf_time.c +++ b/libmagic/src/main/cpp/file/cdf_time.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: cdf_time.c,v 1.16 2017/03/29 15:57:48 christos Exp $") +FILE_RCSID("@(#)$File: cdf_time.c,v 1.18 2019/02/20 02:35:27 christos Exp $") #endif #include @@ -56,7 +56,7 @@ cdf_getdays(int year) for (y = CDF_BASE_YEAR; y < year; y++) days += isleap(y) + 365; - + return days; } @@ -77,7 +77,7 @@ cdf_getday(int year, int days) return days; } -/* +/* * Return the 0...11 month number. */ static int @@ -90,9 +90,9 @@ cdf_getmonth(int year, int days) if (m == 1 && isleap(year)) days--; if (days <= 0) - return (int)m; + return CAST(int, m); } - return (int)m; + return CAST(int, m); } int @@ -108,22 +108,22 @@ cdf_timestamp_to_timespec(struct timespec *ts, cdf_timestamp_t t) ts->tv_nsec = (t % CDF_TIME_PREC) * 100; t /= CDF_TIME_PREC; - tm.tm_sec = (int)(t % 60); + tm.tm_sec = CAST(int, t % 60); t /= 60; - tm.tm_min = (int)(t % 60); + tm.tm_min = CAST(int, t % 60); t /= 60; - tm.tm_hour = (int)(t % 24); + tm.tm_hour = CAST(int, t % 24); t /= 24; /* XXX: Approx */ - tm.tm_year = (int)(CDF_BASE_YEAR + (t / 365)); + tm.tm_year = CAST(int, CDF_BASE_YEAR + (t / 365)); rdays = cdf_getdays(tm.tm_year); t -= rdays - 1; - tm.tm_mday = cdf_getday(tm.tm_year, (int)t); - tm.tm_mon = cdf_getmonth(tm.tm_year, (int)t); + tm.tm_mday = cdf_getday(tm.tm_year, CAST(int, t)); + tm.tm_mon = cdf_getmonth(tm.tm_year, CAST(int, t)); tm.tm_wday = 0; tm.tm_yday = 0; tm.tm_isdst = 0; @@ -172,7 +172,7 @@ cdf_ctime(const time_t *sec, char *buf) if (ptr != NULL) return buf; (void)snprintf(buf, 26, "*Bad* %#16.16" INT64_T_FORMAT "x\n", - (long long)*sec); + CAST(long long, *sec)); return buf; } diff --git a/libmagic/src/main/cpp/file/compress.c b/libmagic/src/main/cpp/file/compress.c index 5d565d5..89fc570 100644 --- a/libmagic/src/main/cpp/file/compress.c +++ b/libmagic/src/main/cpp/file/compress.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -29,13 +29,13 @@ * compress routines: * zmagic() - returns 0 if not recognized, uncompresses and prints * information if recognized - * uncompress(method, old, n, newch) - uncompress old into new, + * uncompress(method, old, n, newch) - uncompress old into new, * using method, return sizeof new */ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: compress.c,v 1.107 2018/04/28 18:48:22 christos Exp $") +FILE_RCSID("@(#)$File: compress.c,v 1.115 2019/02/20 02:35:27 christos Exp $") #endif #include "magic.h" @@ -47,12 +47,10 @@ FILE_RCSID("@(#)$File: compress.c,v 1.107 2018/04/28 18:48:22 christos Exp $") #include #include #include -#ifdef HAVE_SIGNAL_H #include -# ifndef HAVE_SIG_T +#ifndef HAVE_SIG_T typedef void (*sig_t)(int); -# endif /* HAVE_SIG_T */ -#endif +#endif /* HAVE_SIG_T */ #if !defined(__MINGW32__) && !defined(WIN32) #include #endif @@ -62,10 +60,17 @@ typedef void (*sig_t)(int); #if defined(HAVE_SYS_TIME_H) #include #endif + #if defined(HAVE_ZLIB_H) && defined(ZLIBSUPPORT) #define BUILTIN_DECOMPRESS #include #endif + +#if defined(HAVE_BZLIB_H) +#define BUILTIN_BZLIB +#include +#endif + #ifdef DEBUG int tty = -1; #define DPRINTF(...) do { \ @@ -137,30 +142,34 @@ static const char *zstd_args[] = { "zstd", "-cd", NULL }; +#define do_zlib NULL +#define do_bzlib NULL + private const struct { const void *magic; size_t maglen; const char **argv; + void *unused; } compr[] = { - { "\037\235", 2, gzip_args }, /* compressed */ + { "\037\235", 2, gzip_args, NULL }, /* compressed */ /* Uncompress can get stuck; so use gzip first if we have it * Idea from Damien Clark, thanks! */ - { "\037\235", 2, uncompress_args }, /* compressed */ - { "\037\213", 2, gzip_args }, /* gzipped */ - { "\037\236", 2, gzip_args }, /* frozen */ - { "\037\240", 2, gzip_args }, /* SCO LZH */ + { "\037\235", 2, uncompress_args, NULL }, /* compressed */ + { "\037\213", 2, gzip_args, do_zlib }, /* gzipped */ + { "\037\236", 2, gzip_args, NULL }, /* frozen */ + { "\037\240", 2, gzip_args, NULL }, /* SCO LZH */ /* the standard pack utilities do not accept standard input */ - { "\037\036", 2, gzip_args }, /* packed */ - { "PK\3\4", 4, gzip_args }, /* pkzipped, */ + { "\037\036", 2, gzip_args, NULL }, /* packed */ + { "PK\3\4", 4, gzip_args, NULL }, /* pkzipped, */ /* ...only first file examined */ - { "BZh", 3, bzip2_args }, /* bzip2-ed */ - { "LZIP", 4, lzip_args }, /* lzip-ed */ - { "\3757zXZ\0", 6, xz_args }, /* XZ Utils */ - { "LRZI", 4, lrzip_args }, /* LRZIP */ - { "\004\"M\030",4, lz4_args }, /* LZ4 */ - { "\x28\xB5\x2F\xFD", 4, zstd_args }, /* zstd */ + { "BZh", 3, bzip2_args, do_bzlib }, /* bzip2-ed */ + { "LZIP", 4, lzip_args, NULL }, /* lzip-ed */ + { "\3757zXZ\0", 6, xz_args, NULL }, /* XZ Utils */ + { "LRZI", 4, lrzip_args, NULL }, /* LRZIP */ + { "\004\"M\030",4, lz4_args, NULL }, /* LZ4 */ + { "\x28\xB5\x2F\xFD", 4, zstd_args, NULL }, /* zstd */ #ifdef ZLIBSUPPORT - { RCAST(const void *, zlibcmp), 0, zlib_args }, /* zlib */ + { RCAST(const void *, zlibcmp), 0, zlib_args, NULL }, /* zlib */ #endif }; @@ -179,6 +188,11 @@ private int uncompresszlib(const unsigned char *, unsigned char **, size_t, private int uncompressgzipped(const unsigned char *, unsigned char **, size_t, size_t *); #endif +#ifdef BUILTIN_BZLIB +private int uncompressbzlib(const unsigned char *, unsigned char **, size_t, + size_t *, int); +#endif + static int makeerror(unsigned char **, size_t *, const char *, ...) __attribute__((__format__(__printf__, 3, 4))); private const char *methodname(size_t); @@ -210,18 +224,14 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) int urv, prv, rv = 0; int mime = ms->flags & MAGIC_MIME; int fd = b->fd; - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; -#ifdef HAVE_SIGNAL_H sig_t osigpipe; -#endif if ((ms->flags & MAGIC_COMPRESS) == 0) return 0; -#ifdef HAVE_SIGNAL_H osigpipe = signal(SIGPIPE, SIG_IGN); -#endif for (i = 0; i < ncompr; i++) { int zm; if (nbytes < compr[i].maglen) @@ -238,8 +248,8 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) continue; nsz = nbytes; urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz); - DPRINTF("uncompressbuf = %d, %s, %zu\n", urv, (char *)newbuf, - nsz); + DPRINTF("uncompressbuf = %d, %s, %" SIZE_T_FORMAT "u\n", urv, + (char *)newbuf, nsz); switch (urv) { case OKDATA: case ERRDATA: @@ -264,8 +274,11 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) * XXX: If file_buffer fails here, we overwrite * the compressed text. FIXME. */ - if (file_buffer(ms, -1, NULL, buf, nbytes) == -1) + if (file_buffer(ms, -1, NULL, buf, nbytes) == -1) { + if (file_pop_buffer(ms, pb) != NULL) + abort(); goto error; + } if ((rbuf = file_pop_buffer(ms, pb)) != NULL) { if (file_printf(ms, "%s", rbuf) == -1) { free(rbuf); @@ -289,9 +302,7 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) out: DPRINTF("rv = %d\n", rv); -#ifdef HAVE_SIGNAL_H (void)signal(SIGPIPE, osigpipe); -#endif free(newbuf); ms->flags |= MAGIC_COMPRESS; DPRINTF("Zmagic returns %d\n", rv); @@ -367,7 +378,7 @@ sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__))) (void)ioctl(fd, FIONREAD, &t); } - if (t > 0 && (size_t)t < n) { + if (t > 0 && CAST(size_t, t) < n) { n = t; rn = n; } @@ -411,7 +422,9 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, #else { int te; + mode_t ou = umask(0); tfd = mkstemp(buf); + (void)umask(ou); te = errno; (void)unlink(buf); errno = te; @@ -423,11 +436,11 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, return -1; } - if (swrite(tfd, startbuf, nbytes) != (ssize_t)nbytes) + if (swrite(tfd, startbuf, nbytes) != CAST(ssize_t, nbytes)) r = 1; else { while ((r = sread(fd, buf, sizeof(buf), 1)) > 0) - if (swrite(tfd, buf, (size_t)r) != r) + if (swrite(tfd, buf, CAST(size_t, r)) != r) break; } @@ -452,7 +465,7 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, return -1; } (void)close(tfd); - if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { + if (lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1)) { file_badseek(ms); return -1; } @@ -509,7 +522,7 @@ uncompresszlib(const unsigned char *old, unsigned char **newch, int rc; z_stream z; - if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) + if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) return makeerror(newch, n, "No buffer, %s", strerror(errno)); z.next_in = CCAST(Bytef *, old); @@ -529,18 +542,18 @@ uncompresszlib(const unsigned char *old, unsigned char **newch, if (rc != Z_OK && rc != Z_STREAM_END) goto err; - *n = (size_t)z.total_out; + *n = CAST(size_t, z.total_out); rc = inflateEnd(&z); if (rc != Z_OK) goto err; - + /* let's keep the nul-terminate tradition */ (*newch)[*n] = '\0'; return OKDATA; err: - strlcpy((char *)*newch, z.msg ? z.msg : zError(rc), bytes_max); - *n = strlen((char *)*newch); + strlcpy(RCAST(char *, *newch), z.msg ? z.msg : zError(rc), bytes_max); + *n = strlen(RCAST(char *, *newch)); return ERRDATA; } #endif @@ -560,7 +573,7 @@ makeerror(unsigned char **buf, size_t *len, const char *fmt, ...) *len = 0; return NODATA; } - *buf = (unsigned char *)msg; + *buf = RCAST(unsigned char *, msg); *len = strlen(msg); return ERRDATA; } @@ -601,14 +614,14 @@ writechild(int fdp[3][2], const void *old, size_t n) int status; closefd(fdp[STDIN_FILENO], 0); - /* + /* * fork again, to avoid blocking because both * pipes filled */ switch (fork()) { case 0: /* child */ closefd(fdp[STDOUT_FILENO], 0); - if (swrite(fdp[STDIN_FILENO][1], old, n) != (ssize_t)n) { + if (swrite(fdp[STDIN_FILENO][1], old, n) != CAST(ssize_t, n)) { DPRINTF("Write failed (%s)\n", strerror(errno)); exit(1); } @@ -637,17 +650,17 @@ filter_error(unsigned char *ubuf, ssize_t n) char *buf; ubuf[n] = '\0'; - buf = (char *)ubuf; - while (isspace((unsigned char)*buf)) + buf = RCAST(char *, ubuf); + while (isspace(CAST(unsigned char, *buf))) buf++; DPRINTF("Filter error[[[%s]]]\n", buf); - if ((p = strchr((char *)buf, '\n')) != NULL) + if ((p = strchr(CAST(char *, buf), '\n')) != NULL) *p = '\0'; - if ((p = strchr((char *)buf, ';')) != NULL) + if ((p = strchr(CAST(char *, buf), ';')) != NULL) *p = '\0'; - if ((p = strrchr((char *)buf, ':')) != NULL) { + if ((p = strrchr(CAST(char *, buf), ':')) != NULL) { ++p; - while (isspace((unsigned char)*p)) + while (isspace(CAST(unsigned char, *p))) p++; n = strlen(p); memmove(ubuf, p, CAST(size_t, n + 1)); @@ -702,15 +715,15 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old, case 0: /* child */ if (fd != -1) { fdp[STDIN_FILENO][0] = fd; - (void) lseek(fd, (off_t)0, SEEK_SET); + (void) lseek(fd, CAST(off_t, 0), SEEK_SET); } - + for (i = 0; i < __arraycount(fdp); i++) copydesc(CAST(int, i), fdp[i]); (void)execvp(compr[method].argv[0], - (char *const *)(intptr_t)compr[method].argv); - dprintf(STDERR_FILENO, "exec `%s' failed, %s", + RCAST(char *const *, RCAST(intptr_t, compr[method].argv))); + dprintf(STDERR_FILENO, "exec `%s' failed, %s", compr[method].argv[0], strerror(errno)); exit(1); /*NOTREACHED*/ @@ -772,8 +785,8 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old, } closefd(fdp[STDIN_FILENO], 0); - DPRINTF("Returning %p n=%zu rv=%d\n", *newch, *n, rv); - + DPRINTF("Returning %p n=%" SIZE_T_FORMAT "u rv=%d\n", *newch, *n, rv); + return rv; } #endif diff --git a/libmagic/src/main/cpp/file/config.h b/libmagic/src/main/cpp/file/config.h index d7041f6..6431d3a 100644 --- a/libmagic/src/main/cpp/file/config.h +++ b/libmagic/src/main/cpp/file/config.h @@ -87,9 +87,6 @@ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - /* Define to 1 if you have the `localtime_r' function. */ #define HAVE_LOCALTIME_R 1 @@ -112,7 +109,7 @@ #define HAVE_MMAP 1 /* Define to 1 if you have the `newlocale' function. */ -//#define HAVE_NEWLOCALE 1 +#define HAVE_NEWLOCALE 1 /* Define to 1 if you have the `pread' function. */ #define HAVE_PREAD 1 @@ -120,9 +117,6 @@ /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - /* Have sig_t type */ #define HAVE_SIG_T 1 @@ -277,7 +271,7 @@ #define PACKAGE_NAME "file" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "file 5.34" +#define PACKAGE_STRING "file 5.36" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "file" @@ -286,7 +280,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "5.34" +#define PACKAGE_VERSION "5.36" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 @@ -317,7 +311,7 @@ /* Version number of package */ -#define VERSION "5.34" +#define VERSION "5.36" /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ diff --git a/libmagic/src/main/cpp/file/der.c b/libmagic/src/main/cpp/file/der.c index d017b63..8867c56 100644 --- a/libmagic/src/main/cpp/file/der.c +++ b/libmagic/src/main/cpp/file/der.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: der.c,v 1.13 2018/06/23 15:15:26 christos Exp $") +FILE_RCSID("@(#)$File: der.c,v 1.16 2019/02/20 02:35:27 christos Exp $") #endif #endif @@ -56,7 +56,7 @@ FILE_RCSID("@(#)$File: der.c,v 1.13 2018/06/23 15:15:26 christos Exp $") #include #endif -#define DER_BAD ((uint32_t)-1) +#define DER_BAD CAST(uint32_t, -1) #define DER_CLASS_UNIVERSAL 0 #define DER_CLASS_APPLICATION 1 @@ -207,7 +207,7 @@ getlength(const uint8_t *c, size_t *p, size_t l) static const char * der_tag(char *buf, size_t len, uint32_t tag) { - if (tag < DER_TAG_LONG) + if (tag < DER_TAG_LONG) strlcpy(buf, der__tag[tag], len); else snprintf(buf, len, "%#x", tag); @@ -224,11 +224,11 @@ der_data(char *buf, size_t blen, uint32_t tag, const void *q, uint32_t len) case DER_TAG_UTF8_STRING: case DER_TAG_IA5_STRING: case DER_TAG_UTCTIME: - return snprintf(buf, blen, "%.*s", len, (const char *)q); + return snprintf(buf, blen, "%.*s", len, RCAST(const char *, q)); default: break; } - + for (uint32_t i = 0; i < len; i++) { uint32_t z = i << 1; if (z < blen - 2) @@ -245,18 +245,21 @@ der_offs(struct magic_set *ms, struct magic *m, size_t nbytes) if (gettag(b, &offs, len) == DER_BAD) return -1; - DPRINTF(("%s1: %d %zu %u\n", __func__, ms->offset, offs, m->offset)); + DPRINTF(("%s1: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset, + offs, m->offset)); uint32_t tlen = getlength(b, &offs, len); if (tlen == DER_BAD) return -1; - DPRINTF(("%s2: %d %zu %u\n", __func__, ms->offset, offs, tlen)); + DPRINTF(("%s2: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset, + offs, tlen)); offs += ms->offset + m->offset; DPRINTF(("cont_level = %d\n", m->cont_level)); #ifdef DEBUG_DER for (size_t i = 0; i < m->cont_level; i++) - printf("cont_level[%zu] = %u\n", i, ms->c.li[i].off); + printf("cont_level[%" SIZE_T_FORMAT "u] = %u\n", i, + ms->c.li[i].off); #endif if (m->cont_level != 0) { if (offs + tlen > nbytes) @@ -304,22 +307,23 @@ der_cmp(struct magic_set *ms, struct magic *m) s++; goto val; default: - if (!isdigit((unsigned char)*s)) + if (!isdigit(CAST(unsigned char, *s))) return 0; slen = 0; do slen = slen * 10 + *s - '0'; - while (isdigit((unsigned char)*++s)); + while (isdigit(CAST(unsigned char, *++s))); if ((ms->flags & MAGIC_DEBUG) != 0) - fprintf(stderr, "%s: len %zu %u\n", __func__, - slen, tlen); + fprintf(stderr, "%s: len %" SIZE_T_FORMAT "u %u\n", + __func__, slen, tlen); if (tlen != slen) return 0; goto again; } val: - DPRINTF(("%s: before data %zu %u\n", __func__, offs, tlen)); + DPRINTF(("%s: before data %" SIZE_T_FORMAT "u %u\n", __func__, offs, + tlen)); der_data(buf, sizeof(buf), tag, b + offs, tlen); if ((ms->flags & MAGIC_DEBUG) != 0) fprintf(stderr, "%s: data %s %s\n", __func__, buf, s); @@ -343,7 +347,7 @@ printtag(uint32_t tag, const void *q, uint32_t len) default: break; } - + for (uint32_t i = 0; i < len; i++) printf("%.2x", d[i]); printf("\n"); @@ -367,8 +371,9 @@ printdata(size_t level, const void *v, size_t x, size_t l) if (p + x >= ep) break; uint32_t len = getlength(p, &x, ep - p + x); - - printf("%zu %zu-%zu %c,%c,%s,%u:", level, ox, x, + + printf("%" SIZE_T_FORMAT "u %" SIZE_T_FORMAT "u-%" + SIZE_T_FORMAT "u %c,%c,%s,%u:", level, ox, x, der_class[c], der_type[t], der_tag(buf, sizeof(buf), tag), len); q = p + x; diff --git a/libmagic/src/main/cpp/file/dprintf.c b/libmagic/src/main/cpp/file/dprintf.c index 5d9c58b..027a64f 100644 --- a/libmagic/src/main/cpp/file/dprintf.c +++ b/libmagic/src/main/cpp/file/dprintf.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -28,7 +28,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: dprintf.c,v 1.13 2014/12/04 15:56:46 christos Exp $") +FILE_RCSID("@(#)$File: dprintf.c,v 1.2 2018/09/09 20:33:28 christos Exp $") #endif /* lint */ #include diff --git a/libmagic/src/main/cpp/file/elfclass.h b/libmagic/src/main/cpp/file/elfclass.h index 5360b0b..936d8dc 100644 --- a/libmagic/src/main/cpp/file/elfclass.h +++ b/libmagic/src/main/cpp/file/elfclass.h @@ -1,7 +1,7 @@ /* * Copyright (c) Christos Zoulas 2008. * All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -41,8 +41,8 @@ return toomany(ms, "program headers", phnum); flags |= FLAGS_IS_CORE; if (dophn_core(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, - (size_t)elf_getu16(swap, elfhdr.e_phentsize), + CAST(off_t, elf_getu(swap, elfhdr.e_phoff)), phnum, + CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)), fsize, &flags, ¬ecount) == -1) return -1; break; @@ -56,8 +56,8 @@ if (shnum > ms->elf_shnum_max) return toomany(ms, "section", shnum); if (dophn_exec(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, - (size_t)elf_getu16(swap, elfhdr.e_phentsize), + CAST(off_t, elf_getu(swap, elfhdr.e_phoff)), phnum, + CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)), fsize, shnum, &flags, ¬ecount) == -1) return -1; /*FALLTHROUGH*/ @@ -66,10 +66,10 @@ if (shnum > ms->elf_shnum_max) return toomany(ms, "section headers", shnum); if (doshn(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, - (size_t)elf_getu16(swap, elfhdr.e_shentsize), + CAST(off_t, elf_getu(swap, elfhdr.e_shoff)), shnum, + CAST(size_t, elf_getu16(swap, elfhdr.e_shentsize)), fsize, elf_getu16(swap, elfhdr.e_machine), - (int)elf_getu16(swap, elfhdr.e_shstrndx), + CAST(int, elf_getu16(swap, elfhdr.e_shstrndx)), &flags, ¬ecount) == -1) return -1; break; diff --git a/libmagic/src/main/cpp/file/encoding.c b/libmagic/src/main/cpp/file/encoding.c index 3e7b9e5..81cd925 100644 --- a/libmagic/src/main/cpp/file/encoding.c +++ b/libmagic/src/main/cpp/file/encoding.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: encoding.c,v 1.14 2017/11/02 20:25:39 christos Exp $") +FILE_RCSID("@(#)$File: encoding.c,v 1.17 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -49,6 +49,7 @@ private int looks_utf8_with_BOM(const unsigned char *, size_t, unichar *, size_t *); private int looks_utf7(const unsigned char *, size_t, unichar *, size_t *); private int looks_ucs16(const unsigned char *, size_t, unichar *, size_t *); +private int looks_ucs32(const unsigned char *, size_t, unichar *, size_t *); private int looks_latin1(const unsigned char *, size_t, unichar *, size_t *); private int looks_extended(const unsigned char *, size_t, unichar *, size_t *); private void from_ebcdic(const unsigned char *, size_t, unsigned char *); @@ -69,7 +70,7 @@ protected int file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf, size_t *ulen, const char **code, const char **code_mime, const char **type) { - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; size_t mlen; int rv = 1, ucs_type; @@ -88,12 +89,12 @@ file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf, *code_mime = "binary"; mlen = (nbytes + 1) * sizeof((*ubuf)[0]); - if ((*ubuf = CAST(unichar *, calloc((size_t)1, mlen))) == NULL) { + if ((*ubuf = CAST(unichar *, calloc(CAST(size_t, 1), mlen))) == NULL) { file_oomem(ms, mlen); goto done; } mlen = (nbytes + 1) * sizeof(nbuf[0]); - if ((nbuf = CAST(unsigned char *, calloc((size_t)1, mlen))) == NULL) { + if ((nbuf = CAST(unsigned char *, calloc(CAST(size_t, 1), mlen))) == NULL) { file_oomem(ms, mlen); goto done; } @@ -116,6 +117,15 @@ file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf, DPRINTF(("utf8 %" SIZE_T_FORMAT "u\n", *ulen)); *code = "UTF-8 Unicode"; *code_mime = "utf-8"; + } else if ((ucs_type = looks_ucs32(buf, nbytes, *ubuf, ulen)) != 0) { + if (ucs_type == 1) { + *code = "Little-endian UTF-32 Unicode"; + *code_mime = "utf-32le"; + } else { + *code = "Big-endian UTF-32 Unicode"; + *code_mime = "utf-32be"; + } + DPRINTF(("ucs32 %" SIZE_T_FORMAT "u\n", *ulen)); } else if ((ucs_type = looks_ucs16(buf, nbytes, *ubuf, ulen)) != 0) { if (ucs_type == 1) { *code = "Little-endian UTF-16 Unicode"; @@ -410,7 +420,7 @@ looks_utf7(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen) } private int -looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf, +looks_ucs16(const unsigned char *bf, size_t nbytes, unichar *ubf, size_t *ulen) { int bigend; @@ -419,9 +429,9 @@ looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf, if (nbytes < 2) return 0; - if (buf[0] == 0xff && buf[1] == 0xfe) + if (bf[0] == 0xff && bf[1] == 0xfe) bigend = 0; - else if (buf[0] == 0xfe && buf[1] == 0xff) + else if (bf[0] == 0xfe && bf[1] == 0xff) bigend = 1; else return 0; @@ -432,20 +442,58 @@ looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf, /* XXX fix to properly handle chars > 65536 */ if (bigend) - ubuf[(*ulen)++] = buf[i + 1] + 256 * buf[i]; + ubf[(*ulen)++] = bf[i + 1] + 256 * bf[i]; else - ubuf[(*ulen)++] = buf[i] + 256 * buf[i + 1]; + ubf[(*ulen)++] = bf[i] + 256 * bf[i + 1]; - if (ubuf[*ulen - 1] == 0xfffe) + if (ubf[*ulen - 1] == 0xfffe) return 0; - if (ubuf[*ulen - 1] < 128 && - text_chars[(size_t)ubuf[*ulen - 1]] != T) + if (ubf[*ulen - 1] < 128 && + text_chars[CAST(size_t, ubf[*ulen - 1])] != T) return 0; } return 1 + bigend; } +private int +looks_ucs32(const unsigned char *bf, size_t nbytes, unichar *ubf, + size_t *ulen) +{ + int bigend; + size_t i; + + if (nbytes < 4) + return 0; + + if (bf[0] == 0xff && bf[1] == 0xfe && bf[2] == 0 && bf[3] == 0) + bigend = 0; + else if (bf[0] == 0 && bf[1] == 0 && bf[2] == 0xfe && bf[3] == 0xff) + bigend = 1; + else + return 0; + + *ulen = 0; + + for (i = 4; i + 1 < nbytes; i += 4) { + /* XXX fix to properly handle chars > 65536 */ + + if (bigend) + ubf[(*ulen)++] = bf[i + 3] | (bf[i + 2] << 8) + | (bf[i + 1] << 16) | bf[i] << 24; + else + ubf[(*ulen)++] = bf[i] | (bf[i + 1] << 8) + | (bf[i + 2] << 16) | (bf[i + 3] << 24); + + if (ubf[*ulen - 1] == 0xfffe) + return 0; + if (ubf[*ulen - 1] < 128 && + text_chars[CAST(size_t, ubf[*ulen - 1])] != T) + return 0; + } + + return 1 + bigend; +} #undef F #undef T #undef I diff --git a/libmagic/src/main/cpp/file/file.c b/libmagic/src/main/cpp/file/file.c index 87dd1bb..5f0303e 100644 --- a/libmagic/src/main/cpp/file/file.c +++ b/libmagic/src/main/cpp/file/file.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: file.c,v 1.175 2018/03/02 16:11:37 christos Exp $") +FILE_RCSID("@(#)$File: file.c,v 1.179 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -128,6 +128,7 @@ private const struct { { "encoding", MAGIC_NO_CHECK_ENCODING }, { "soft", MAGIC_NO_CHECK_SOFT }, { "tar", MAGIC_NO_CHECK_TAR }, + { "json", MAGIC_NO_CHECK_JSON }, { "text", MAGIC_NO_CHECK_TEXT }, /* synonym for ascii */ { "tokens", MAGIC_NO_CHECK_TOKENS }, /* OBSOLETE: ignored for backwards compatibility */ }; @@ -136,14 +137,15 @@ private struct { const char *name; int tag; size_t value; + int set; } pm[] = { - { "indir", MAGIC_PARAM_INDIR_MAX, 0 }, - { "name", MAGIC_PARAM_NAME_MAX, 0 }, - { "elf_phnum", MAGIC_PARAM_ELF_PHNUM_MAX, 0 }, - { "elf_shnum", MAGIC_PARAM_ELF_SHNUM_MAX, 0 }, - { "elf_notes", MAGIC_PARAM_ELF_NOTES_MAX, 0 }, - { "regex", MAGIC_PARAM_REGEX_MAX, 0 }, - { "bytes", MAGIC_PARAM_BYTES_MAX, 0 }, + { "indir", MAGIC_PARAM_INDIR_MAX, 0, 0 }, + { "name", MAGIC_PARAM_NAME_MAX, 0, 0 }, + { "elf_phnum", MAGIC_PARAM_ELF_PHNUM_MAX, 0, 0 }, + { "elf_shnum", MAGIC_PARAM_ELF_SHNUM_MAX, 0, 0 }, + { "elf_notes", MAGIC_PARAM_ELF_NOTES_MAX, 0, 0 }, + { "regex", MAGIC_PARAM_REGEX_MAX, 0, 0 }, + { "bytes", MAGIC_PARAM_BYTES_MAX, 0, 0 }, }; private int posixly; @@ -398,7 +400,8 @@ main(int argc, char *argv[]) } else { size_t j, wid, nw; - for (wid = 0, j = (size_t)optind; j < (size_t)argc; j++) { + for (wid = 0, j = CAST(size_t, optind); j < CAST(size_t, argc); + j++) { nw = file_mbswidth(argv[j]); if (nw > wid) wid = nw; @@ -426,7 +429,7 @@ applyparam(magic_t magic) size_t i; for (i = 0; i < __arraycount(pm); i++) { - if (pm[i].value == 0) + if (!pm[i].set) continue; if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1) file_err(EXIT_FAILURE, "Can't set %s", pm[i].name); @@ -446,6 +449,7 @@ setparam(const char *p) if (strncmp(p, pm[i].name, s - p) != 0) continue; pm[i].value = atoi(s + 1); + pm[i].set = 1; return; } badparm: @@ -534,9 +538,8 @@ process(struct magic_set *ms, const char *inname, int wid) (void)putc('\0', stdout); if (nulsep < 2) { (void)printf("%s", separator); - (void)printf("%*s ", - (int) (nopad ? 0 : (wid - file_mbswidth(inname))), - ""); + (void)printf("%*s ", CAST(int, nopad ? 0 + : (wid - file_mbswidth(inname))), ""); } } @@ -563,8 +566,8 @@ file_mbswidth(const char *s) while (n > 0) { bytesconsumed = mbrtowc(&nextchar, s, n, &state); - if (bytesconsumed == (size_t)(-1) || - bytesconsumed == (size_t)(-2)) { + if (bytesconsumed == CAST(size_t, -1) || + bytesconsumed == CAST(size_t, -2)) { /* Something went wrong, return something reasonable */ return old_n; } @@ -623,13 +626,13 @@ docprint(const char *opts, int def) for (sp = p - 1; sp > opts && *sp == ' '; sp--) continue; - fprintf(stdout, "%.*s", (int)(p - opts), opts); + fprintf(stdout, "%.*s", CAST(int, p - opts), opts); comma = 0; for (i = 0; i < __arraycount(nv); i++) { fprintf(stdout, "%s%s", comma++ ? ", " : "", nv[i].name); - if (i && i % 5 == 0) { - fprintf(stdout, ",\n%*s", (int)(p - sp - 1), ""); + if (i && i % 5 == 0 && i != __arraycount(nv) - 1) { + fprintf(stdout, ",\n%*s", CAST(int, p - sp - 1), ""); comma = 0; } } @@ -653,7 +656,7 @@ help(void) #include "file_opts.h" #undef OPT #undef OPT_LONGONLY - fprintf(stdout, "\nReport bugs to http://bugs.gw.com/\n"); + fprintf(stdout, "\nReport bugs to https://bugs.astron.com/\n"); exit(EXIT_SUCCESS); } diff --git a/libmagic/src/main/cpp/file/file.h b/libmagic/src/main/cpp/file/file.h index 57a84a8..f8e0835 100644 --- a/libmagic/src/main/cpp/file/file.h +++ b/libmagic/src/main/cpp/file/file.h @@ -27,7 +27,7 @@ */ /* * file.h - definitions for file(1) program - * @(#)$File: file.h,v 1.193 2018/05/24 18:09:17 christos Exp $ + * @(#)$File: file.h,v 1.202 2019/02/18 17:46:56 christos Exp $ */ #ifndef __file_h__ @@ -40,6 +40,9 @@ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif #ifdef WIN32 #ifdef _WIN64 @@ -379,7 +382,7 @@ struct mlist { #define CCAST(T, b) const_cast(b) #else #define CAST(T, b) ((T)(b)) -#define RCAST(T, b) ((T)(b)) +#define RCAST(T, b) ((T)(uintptr_t)(b)) #define CCAST(T, b) ((T)(uintptr_t)(b)) #endif @@ -450,6 +453,7 @@ struct stat; protected const char *file_fmttime(uint64_t, int, char *); protected struct magic_set *file_ms_alloc(int); protected void file_ms_free(struct magic_set *); +protected int file_default(struct magic_set *, size_t); protected int file_buffer(struct magic_set *, int, const char *, const void *, size_t); protected int file_fsmagic(struct magic_set *, const char *, struct stat *); @@ -473,6 +477,7 @@ protected int file_ascmagic_with_encoding(struct magic_set *, const struct buffer *, unichar *, size_t, const char *, const char *, int); protected int file_encoding(struct magic_set *, const struct buffer *, unichar **, size_t *, const char **, const char **, const char **); +protected int file_is_json(struct magic_set *, const struct buffer *); protected int file_is_tar(struct magic_set *, const struct buffer *); protected int file_softmagic(struct magic_set *, const struct buffer *, uint16_t *, uint16_t *, int, int); @@ -501,7 +506,7 @@ protected int file_looks_utf8(const unsigned char *, size_t, unichar *, size_t *); protected size_t file_pstring_length_size(const struct magic *); protected size_t file_pstring_get_length(const struct magic *, const char *); -protected char * file_printable(char *, size_t, const char *); +protected char * file_printable(char *, size_t, const char *, size_t); #ifdef __EMX__ protected int file_os2_apptype(struct magic_set *, const char *, const void *, size_t); @@ -511,9 +516,7 @@ protected void buffer_init(struct buffer *, int, const void *, size_t); protected void buffer_fini(struct buffer *); protected int buffer_fill(const struct buffer *); -#if defined(HAVE_LOCALE_H) #include -#endif #if defined(HAVE_XLOCALE_H) #include #endif @@ -600,17 +603,17 @@ struct tm *gmtime_r(const time_t *, struct tm *); struct tm *localtime_r(const time_t *, struct tm *); #endif #ifndef HAVE_FMTCHECK -const char *fmtcheck(const char *, const char *) +const char *fmtcheck(const char *, const char *) __attribute__((__format_arg__(2))); #endif #ifdef HAVE_LIBSECCOMP -// basic filter +// basic filter // this mode should not interfere with normal operations // only some dangerous syscalls are blacklisted int enable_sandbox_basic(void); -// enhanced filter +// enhanced filter // this mode allows only the necessary syscalls used during normal operation // extensive testing required !!! int enable_sandbox_full(void); @@ -634,6 +637,9 @@ protected void file_warnx(const char *, ...) #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef O_NONBLOCK +#define O_NONBLOCK 0 +#endif #ifndef __cplusplus #if defined(__GNUC__) && (__GNUC__ >= 3) diff --git a/libmagic/src/main/cpp/file/fmtcheck.c b/libmagic/src/main/cpp/file/fmtcheck.c index 486aa08..fcad436 100644 --- a/libmagic/src/main/cpp/file/fmtcheck.c +++ b/libmagic/src/main/cpp/file/fmtcheck.c @@ -235,7 +235,7 @@ fmtcheck(const char *f1, const char *f2) EFT f1t, f2t; if (!f1) return f2; - + f1p = f1; f1t = FMTCHECK_START; f2p = f2; diff --git a/libmagic/src/main/cpp/file/fsmagic.c b/libmagic/src/main/cpp/file/fsmagic.c index c0a437a..3d74255 100644 --- a/libmagic/src/main/cpp/file/fsmagic.c +++ b/libmagic/src/main/cpp/file/fsmagic.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: fsmagic.c,v 1.77 2017/05/24 19:17:50 christos Exp $") +FILE_RCSID("@(#)$File: fsmagic.c,v 1.79 2018/10/02 00:38:33 christos Exp $") #endif /* lint */ #include "magic.h" @@ -77,7 +77,7 @@ bad_link(struct magic_set *ms, int err, char *buf) file_error(ms, err, "broken symbolic link to %s", buf); return -1; - } + } if (file_printf(ms, "broken symbolic link to %s", buf) == -1) return -1; } @@ -174,17 +174,17 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) return -1; #endif #ifdef S_ISGID - if (sb->st_mode & S_ISGID) + if (sb->st_mode & S_ISGID) if (file_printf(ms, "%ssetgid", COMMA) == -1) return -1; #endif #ifdef S_ISVTX - if (sb->st_mode & S_ISVTX) + if (sb->st_mode & S_ISVTX) if (file_printf(ms, "%ssticky", COMMA) == -1) return -1; #endif } - + switch (sb->st_mode & S_IFMT) { case S_IFDIR: if (mime) { @@ -196,7 +196,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) break; #ifdef S_IFCHR case S_IFCHR: - /* + /* * If -s has been specified, treat character special files * like ordinary files. Otherwise, just report that they * are block special files and go on to the next file. @@ -231,7 +231,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) #endif #ifdef S_IFBLK case S_IFBLK: - /* + /* * If -s has been specified, treat block special files * like ordinary files. Otherwise, just report that they * are block special files and go on to the next file. @@ -308,6 +308,15 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) buf[nch] = '\0'; /* readlink(2) does not do this */ /* If broken symlink, say so and quit early. */ +#ifdef __linux__ + /* + * linux procfs/devfs makes symlinks like pipe:[3515864880] + * that we can't stat their readlink output, so stat the + * original filename instead. + */ + if (stat(fn, &tstatbuf) < 0) + return bad_link(ms, errno, buf); +#else if (*buf == '/') { if (stat(buf, &tstatbuf) < 0) return bad_link(ms, errno, buf); @@ -320,7 +329,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) } else { if (tmp - fn + 1 > BUFSIZ) { if (ms->flags & MAGIC_ERROR) { - file_error(ms, 0, + file_error(ms, 0, "path too long: `%s'", buf); return -1; } @@ -345,6 +354,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) if (stat(tmp, &tstatbuf) < 0) return bad_link(ms, errno, buf); } +#endif /* Otherwise, handle it. */ if ((ms->flags & MAGIC_SYMLINK) != 0) { diff --git a/libmagic/src/main/cpp/file/funcs.c b/libmagic/src/main/cpp/file/funcs.c index 0bf92fe..eca99ad 100644 --- a/libmagic/src/main/cpp/file/funcs.c +++ b/libmagic/src/main/cpp/file/funcs.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: funcs.c,v 1.95 2018/05/24 18:09:17 christos Exp $") +FILE_RCSID("@(#)$File: funcs.c,v 1.102 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -42,9 +42,7 @@ FILE_RCSID("@(#)$File: funcs.c,v 1.95 2018/05/24 18:09:17 christos Exp $") #if defined(HAVE_WCTYPE_H) #include #endif -#if defined(HAVE_LIMITS_H) #include -#endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)~0) @@ -107,13 +105,13 @@ file_error_core(struct magic_set *ms, int error, const char *f, va_list va, if (lineno != 0) { free(ms->o.buf); ms->o.buf = NULL; - file_printf(ms, "line %" SIZE_T_FORMAT "u:", lineno); + (void)file_printf(ms, "line %" SIZE_T_FORMAT "u:", lineno); } if (ms->o.buf && *ms->o.buf) - file_printf(ms, " "); - file_vprintf(ms, f, va); + (void)file_printf(ms, " "); + (void)file_vprintf(ms, f, va); if (error > 0) - file_printf(ms, " (%s)", strerror(error)); + (void)file_printf(ms, " (%s)", strerror(error)); ms->event_flags |= EVENT_HAD_ERR; ms->error = error; } @@ -172,6 +170,35 @@ checkdone(struct magic_set *ms, int *rv) return 0; } +protected int +file_default(struct magic_set *ms, size_t nb) +{ + if (ms->flags & MAGIC_MIME) { + if ((ms->flags & MAGIC_MIME_TYPE) && + file_printf(ms, "application/%s", + nb ? "octet-stream" : "x-empty") == -1) + return -1; + return 1; + } + if (ms->flags & MAGIC_APPLE) { + if (file_printf(ms, "UNKNUNKN") == -1) + return -1; + return 1; + } + if (ms->flags & MAGIC_EXTENSION) { + if (file_printf(ms, "???") == -1) + return -1; + return 1; + } + return 0; +} + +/* + * The magic detection functions return: + * 1: found + * 0: not found + * -1: error + */ /*ARGSUSED*/ protected int file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__unused__)), @@ -180,7 +207,6 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u int m = 0, rv = 0, looks_text = 0; const char *code = NULL; const char *code_mime = "binary"; - const char *type = "application/octet-stream"; const char *def = "data"; const char *ftype = NULL; char *rbuf = NULL; @@ -191,7 +217,6 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u if (nb == 0) { def = "empty"; - type = "application/x-empty"; goto simple; } else if (nb == 1) { def = "very short file (no magic)"; @@ -240,6 +265,17 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u } } + /* Check if we have a JSON file */ + if ((ms->flags & MAGIC_NO_CHECK_JSON) == 0) { + m = file_is_json(ms, &b); + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, "[try json %d]\n", m); + if (m) { + if (checkdone(ms, &rv)) + goto done; + } + } + /* Check if we have a CDF file */ if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) { m = file_trycdf(ms, &b); @@ -268,7 +304,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u rv = file_tryelf(ms, &b); rbuf = file_pop_buffer(ms, pb); - if (rv != 1) { + if (rv == -1) { free(rbuf); rbuf = NULL; } @@ -306,20 +342,12 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u simple: /* give up */ - m = 1; - if (ms->flags & MAGIC_MIME) { - if ((ms->flags & MAGIC_MIME_TYPE) && - file_printf(ms, "%s", type) == -1) - rv = -1; - } else if (ms->flags & MAGIC_APPLE) { - if (file_printf(ms, "UNKNUNKN") == -1) - rv = -1; - } else if (ms->flags & MAGIC_EXTENSION) { - if (file_printf(ms, "???") == -1) - rv = -1; - } else { - if (file_printf(ms, "%s", def) == -1) - rv = -1; + if (m == 0) { + m = 1; + rv = file_default(ms, nb); + if (rv == 0) + if (file_printf(ms, "%s", def) == -1) + rv = -1; } done: if ((ms->flags & MAGIC_MIME_ENCODING) != 0) { @@ -364,9 +392,9 @@ file_reset(struct magic_set *ms, int checkloaded) #define OCTALIFY(n, o) \ /*LINTED*/ \ (void)(*(n)++ = '\\', \ - *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \ - *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \ - *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \ + *(n)++ = ((CAST(uint32_t, *(o)) >> 6) & 3) + '0', \ + *(n)++ = ((CAST(uint32_t, *(o)) >> 3) & 7) + '0', \ + *(n)++ = ((CAST(uint32_t, *(o)) >> 0) & 7) + '0', \ (o)++) protected const char * @@ -412,9 +440,9 @@ file_getbuffer(struct magic_set *ms) while (op < eop) { bytesconsumed = mbrtowc(&nextchar, op, - (size_t)(eop - op), &state); - if (bytesconsumed == (size_t)(-1) || - bytesconsumed == (size_t)(-2)) { + CAST(size_t, eop - op), &state); + if (bytesconsumed == CAST(size_t, -1) || + bytesconsumed == CAST(size_t, -2)) { mb_conv = 0; break; } @@ -437,7 +465,7 @@ file_getbuffer(struct magic_set *ms) #endif for (np = ms->o.pbuf, op = ms->o.buf; *op;) { - if (isprint((unsigned char)*op)) { + if (isprint(CAST(unsigned char, *op))) { *np++ = *op++; } else { OCTALIFY(np, op); @@ -595,12 +623,13 @@ file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) * convert string to ascii printable format. */ protected char * -file_printable(char *buf, size_t bufsiz, const char *str) +file_printable(char *buf, size_t bufsiz, const char *str, size_t slen) { - char *ptr, *eptr; - const unsigned char *s = (const unsigned char *)str; + char *ptr, *eptr = buf + bufsiz - 1; + const unsigned char *s = RCAST(const unsigned char *, str); + const unsigned char *es = s + slen; - for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) { + for (ptr = buf; ptr < eptr && s < es && *s; s++) { if (isprint(*s)) { *ptr++ = *s; continue; diff --git a/libmagic/src/main/cpp/file/getopt_long.c b/libmagic/src/main/cpp/file/getopt_long.c deleted file mode 100644 index f0fb1b0..0000000 --- a/libmagic/src/main/cpp/file/getopt_long.c +++ /dev/null @@ -1,498 +0,0 @@ -/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */ - -/*- - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Dieter Baron and Thomas Klausner. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "file.h" - -#ifndef lint -FILE_RCSID("@(#)$File: getopt_long.c,v 1.5 2009/02/03 20:27:51 christos Exp $") -#endif /* lint */ - -#include -#ifdef HAVE_ERR_H -#include -#else -#define warnx printf -#endif -#include -#if defined(HAVE_GETOPT_H) && defined(HAVE_STRUCT_OPTION) -#include -#else -#include "mygetopt.h" -#endif -#include -#include - -#define REPLACE_GETOPT - -#ifndef _DIAGASSERT -#define _DIAGASSERT assert -#endif - -#ifdef REPLACE_GETOPT -#ifdef __weak_alias -__weak_alias(getopt,_getopt) -#endif -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ -#elif HAVE_NBTOOL_CONFIG_H && !HAVE_DECL_OPTRESET -static int optreset; -#endif - -#ifdef __weak_alias -__weak_alias(getopt_long,_getopt_long) -#endif - -#define IGNORE_FIRST (*options == '-' || *options == '+') -#define PRINT_ERROR ((opterr) && ((*options != ':') \ - || (IGNORE_FIRST && options[1] != ':'))) -#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) -#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) -/* XXX: GNU ignores PC if *options == '-' */ -#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') - -/* return values */ -#define BADCH (int)'?' -#define BADARG ((IGNORE_FIRST && options[1] == ':') \ - || (*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 - -#define EMSG "" - -static int getopt_internal(int, char **, const char *); -static int gcd(int, int); -static void permute_args(int, int, int, char **); - -static const char *place = EMSG; /* option letter processing */ - -/* XXX: set optreset to 1 rather than these two */ -static int nonopt_start = -1; /* first non option argument (for permute) */ -static int nonopt_end = -1; /* first option after non options (for permute) */ - -/* Error messages */ -static const char recargchar[] = "option requires an argument -- %c"; -static const char recargstring[] = "option requires an argument -- %s"; -static const char ambig[] = "ambiguous option -- %.*s"; -static const char noarg[] = "option doesn't take an argument -- %.*s"; -static const char illoptchar[] = "unknown option -- %c"; -static const char illoptstring[] = "unknown option -- %s"; - - -/* - * Compute the greatest common divisor of a and b. - */ -static int -gcd(a, b) - int a; - int b; -{ - int c; - - c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } - - return b; -} - -/* - * Exchange the block from nonopt_start to nonopt_end with the block - * from nonopt_end to opt_end (keeping the same order of arguments - * in each block). - */ -static void -permute_args(panonopt_start, panonopt_end, opt_end, nargv) - int panonopt_start; - int panonopt_end; - int opt_end; - char **nargv; -{ - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; - - _DIAGASSERT(nargv != NULL); - - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; - - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - nargv[pos] = nargv[cstart]; - nargv[cstart] = swap; - } - } -} - -/* - * getopt_internal -- - * Parse argc/argv argument vector. Called by user level routines. - * Returns -2 if -- is found (can be long option or end of options marker). - */ -static int -getopt_internal(nargc, nargv, options) - int nargc; - char **nargv; - const char *options; -{ - char *oli; /* option letter list index */ - int optchar; - - _DIAGASSERT(nargv != NULL); - _DIAGASSERT(options != NULL); - - optarg = NULL; - - /* - * XXX Some programs (like rsyncd) expect to be able to - * XXX re-initialize optind to 0 and have getopt_long(3) - * XXX properly function again. Work around this braindamage. - */ - if (optind == 0) - optind = 1; - - if (optreset) - nonopt_start = nonopt_end = -1; -start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return -1; - } - if ((*(place = nargv[optind]) != '-') - || (place[1] == '\0')) { /* found non-option */ - place = EMSG; - if (IN_ORDER) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return INORDER; - } - if (!PERMUTE) { - /* - * if no permutation wanted, stop parsing - * at first non-option - */ - return -1; - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; - if (place[1] && *++place == '-') { /* found "--" */ - place++; - return -2; - } - } - if ((optchar = (int)*place++) == (int)':' || - (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { - /* option letter unknown or ':' */ - if (!*place) - ++optind; - if (PRINT_ERROR) - warnx(illoptchar, optchar); - optopt = optchar; - return BADCH; - } - if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ - /* XXX: what if no long options provided (called by getopt)? */ - if (*place) - return -2; - - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return BADARG; - } else /* white space */ - place = nargv[optind]; - /* - * Handle -W arg the same as --arg (which causes getopt to - * stop parsing). - */ - return -2; - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; - } else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = (char *)place; - /* XXX: disable test for :: if PC? (GNU doesn't) */ - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return BADARG; - } else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return optchar; -} - -#ifdef REPLACE_GETOPT -/* - * getopt -- - * Parse argc/argv argument vector. - * - * [eventually this will replace the real getopt] - */ -int -getopt(nargc, nargv, options) - int nargc; - char * const *nargv; - const char *options; -{ - int retval; - - _DIAGASSERT(nargv != NULL); - _DIAGASSERT(options != NULL); - - retval = getopt_internal(nargc, (char **)nargv, options); - if (retval == -2) { - ++optind; - /* - * We found an option (--), so if we skipped non-options, - * we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, optind, - (char **)nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - retval = -1; - } - return retval; -} -#endif - -/* - * getopt_long -- - * Parse argc/argv argument vector. - */ -int -getopt_long(nargc, nargv, options, long_options, idx) - int nargc; - char * const *nargv; - const char *options; - const struct option *long_options; - int *idx; -{ - int retval; - -#define IDENTICAL_INTERPRETATION(_x, _y) \ - (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ - long_options[(_x)].flag == long_options[(_y)].flag && \ - long_options[(_x)].val == long_options[(_y)].val) - - _DIAGASSERT(nargv != NULL); - _DIAGASSERT(options != NULL); - _DIAGASSERT(long_options != NULL); - /* idx may be NULL */ - - retval = getopt_internal(nargc, (char **)nargv, options); - if (retval == -2) { - char *current_argv, *has_equal; - size_t current_argv_len; - int i, ambiguous, match; - - current_argv = (char *)place; - match = -1; - ambiguous = 0; - - optind++; - place = EMSG; - - if (*current_argv == '\0') { /* found "--" */ - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, (char **)nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return -1; - } - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; - - if (strlen(long_options[i].name) == - (unsigned)current_argv_len) { - /* exact match */ - match = i; - ambiguous = 0; - break; - } - if (match == -1) /* partial match */ - match = i; - else if (!IDENTICAL_INTERPRETATION(i, match)) - ambiguous = 1; - } - if (ambiguous) { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); - optopt = 0; - return BADCH; - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of - * flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return BADARG; - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use - * next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' - * indicates no error should be generated - */ - if (PRINT_ERROR) - warnx(recargstring, current_argv); - /* - * XXX: GNU sets optopt to val regardless - * of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return BADARG; - } - } else { /* unknown option */ - if (PRINT_ERROR) - warnx(illoptstring, current_argv); - optopt = 0; - return BADCH; - } - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - retval = 0; - } else - retval = long_options[match].val; - if (idx) - *idx = match; - } - return retval; -#undef IDENTICAL_INTERPRETATION -} diff --git a/libmagic/src/main/cpp/file/is_json.c b/libmagic/src/main/cpp/file/is_json.c new file mode 100644 index 0000000..a8a6eca --- /dev/null +++ b/libmagic/src/main/cpp/file/is_json.c @@ -0,0 +1,455 @@ +/*- + * Copyright (c) 2018 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Parse JSON object serialization format (RFC-7159) + */ + +#ifndef TEST +#include "file.h" + +#ifndef lint +FILE_RCSID("@(#)$File: is_json.c,v 1.12 2018/10/19 00:26:26 christos Exp $") +#endif + +#include +#include "magic.h" +#endif + +#ifdef DEBUG +#include +#define DPRINTF(a, b, c) \ + printf("%s [%.2x/%c] %.20s\n", (a), *(b), *(b), (const char *)(c)) +#else +#define DPRINTF(a, b, c) do { } while (/*CONSTCOND*/0) +#endif + +#define JSON_ARRAY 0 +#define JSON_CONSTANT 1 +#define JSON_NUMBER 2 +#define JSON_OBJECT 3 +#define JSON_STRING 4 +#define JSON_MAX 5 + +/* + * if JSON_COUNT != 0: + * count all the objects, require that we have the whole data file + * otherwise: + * stop if we find an object or an array + */ +#ifndef JSON_COUNT +#define JSON_COUNT 0 +#endif + +static int json_parse(const unsigned char **, const unsigned char *, size_t *, + size_t); + +static int +json_isspace(const unsigned char uc) +{ + switch (uc) { + case ' ': + case '\n': + case '\r': + case '\t': + return 1; + default: + return 0; + } +} + +static int +json_isdigit(unsigned char uc) +{ + switch (uc) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return 1; + default: + return 0; + } +} + +static int +json_isxdigit(unsigned char uc) +{ + if (json_isdigit(uc)) + return 1; + switch (uc) { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return 1; + default: + return 0; + } +} + +static const unsigned char * +json_skip_space(const unsigned char *uc, const unsigned char *ue) +{ + while (uc < ue && json_isspace(*uc)) + uc++; + return uc; +} + +static int +json_parse_string(const unsigned char **ucp, const unsigned char *ue) +{ + const unsigned char *uc = *ucp; + size_t i; + + DPRINTF("Parse string: ", uc, *ucp); + while (uc < ue) { + switch (*uc++) { + case '\0': + goto out; + case '\\': + if (uc == ue) + goto out; + switch (*uc++) { + case '\0': + goto out; + case '"': + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + continue; + case 'u': + if (ue - uc < 4) { + uc = ue; + goto out; + } + for (i = 0; i < 4; i++) + if (!json_isxdigit(*uc++)) + goto out; + continue; + default: + goto out; + } + case '"': + *ucp = uc; + return 1; + default: + continue; + } + } +out: + DPRINTF("Bad string: ", uc, *ucp); + *ucp = uc; + return 0; +} + +static int +json_parse_array(const unsigned char **ucp, const unsigned char *ue, + size_t *st, size_t lvl) +{ + const unsigned char *uc = *ucp; + + DPRINTF("Parse array: ", uc, *ucp); + while (uc < ue) { + if (!json_parse(&uc, ue, st, lvl + 1)) + goto out; + if (uc == ue) + goto out; + switch (*uc) { + case ',': + uc++; + continue; + case ']': + *ucp = uc + 1; + return 1; + default: + goto out; + } + } +out: + DPRINTF("Bad array: ", uc, *ucp); + *ucp = uc; + return 0; +} + +static int +json_parse_object(const unsigned char **ucp, const unsigned char *ue, + size_t *st, size_t lvl) +{ + const unsigned char *uc = *ucp; + DPRINTF("Parse object: ", uc, *ucp); + while (uc < ue) { + uc = json_skip_space(uc, ue); + if (uc == ue) + goto out; + if (*uc++ != '"') { + DPRINTF("not string", uc, *ucp); + goto out; + } + DPRINTF("next field", uc, *ucp); + if (!json_parse_string(&uc, ue)) { + DPRINTF("not string", uc, *ucp); + goto out; + } + uc = json_skip_space(uc, ue); + if (uc == ue) + goto out; + if (*uc++ != ':') { + DPRINTF("not colon", uc, *ucp); + goto out; + } + if (!json_parse(&uc, ue, st, lvl + 1)) { + DPRINTF("not json", uc, *ucp); + goto out; + } + if (uc == ue) + goto out; + switch (*uc++) { + case ',': + continue; + case '}': /* { */ + *ucp = uc; + DPRINTF("Good object: ", uc, *ucp); + return 1; + default: + *ucp = uc - 1; + DPRINTF("not more", uc, *ucp); + goto out; + } + } +out: + DPRINTF("Bad object: ", uc, *ucp); + *ucp = uc; + return 0; +} + +static int +json_parse_number(const unsigned char **ucp, const unsigned char *ue) +{ + const unsigned char *uc = *ucp; + int got = 0; + + DPRINTF("Parse number: ", uc, *ucp); + if (uc == ue) + return 0; + if (*uc == '-') + uc++; + + for (; uc < ue; uc++) { + if (!json_isdigit(*uc)) + break; + got = 1; + } + if (uc == ue) + goto out; + if (*uc == '.') + uc++; + for (; uc < ue; uc++) { + if (!json_isdigit(*uc)) + break; + got = 1; + } + if (uc == ue) + goto out; + if (got && (*uc == 'e' || *uc == 'E')) { + uc++; + got = 0; + if (uc == ue) + goto out; + if (*uc == '+' || *uc == '-') + uc++; + for (; uc < ue; uc++) { + if (!json_isdigit(*uc)) + break; + got = 1; + } + } +out: + if (!got) + DPRINTF("Bad number: ", uc, *ucp); + else + DPRINTF("Good number: ", uc, *ucp); + *ucp = uc; + return got; +} + +static int +json_parse_const(const unsigned char **ucp, const unsigned char *ue, + const char *str, size_t len) +{ + const unsigned char *uc = *ucp; + + DPRINTF("Parse const: ", uc, *ucp); + for (len--; uc < ue && --len;) { + if (*uc++ == *++str) + continue; + } + if (len) + DPRINTF("Bad const: ", uc, *ucp); + *ucp = uc; + return len == 0; +} + +static int +json_parse(const unsigned char **ucp, const unsigned char *ue, + size_t *st, size_t lvl) +{ + const unsigned char *uc; + int rv = 0; + int t; + + uc = json_skip_space(*ucp, ue); + if (uc == ue) + goto out; + + // Avoid recursion + if (lvl > 20) + return 0; +#if JSON_COUNT + /* bail quickly if not counting */ + if (lvl > 1 && (st[JSON_OBJECT] || st[JSON_ARRAY])) + return 1; +#endif + + DPRINTF("Parse general: ", uc, *ucp); + switch (*uc++) { + case '"': + rv = json_parse_string(&uc, ue); + t = JSON_STRING; + break; + case '[': + rv = json_parse_array(&uc, ue, st, lvl + 1); + t = JSON_ARRAY; + break; + case '{': /* '}' */ + rv = json_parse_object(&uc, ue, st, lvl + 1); + t = JSON_OBJECT; + break; + case 't': + rv = json_parse_const(&uc, ue, "true", sizeof("true")); + t = JSON_CONSTANT; + break; + case 'f': + rv = json_parse_const(&uc, ue, "false", sizeof("false")); + t = JSON_CONSTANT; + break; + case 'n': + rv = json_parse_const(&uc, ue, "null", sizeof("null")); + t = JSON_CONSTANT; + break; + default: + --uc; + rv = json_parse_number(&uc, ue); + t = JSON_NUMBER; + break; + } + if (rv) + st[t]++; + uc = json_skip_space(uc, ue); +out: + *ucp = uc; + DPRINTF("End general: ", uc, *ucp); + if (lvl == 0) + return rv && (st[JSON_ARRAY] || st[JSON_OBJECT]); + return rv; +} + +#ifndef TEST +int +file_is_json(struct magic_set *ms, const struct buffer *b) +{ + const unsigned char *uc = CAST(const unsigned char *, b->fbuf); + const unsigned char *ue = uc + b->flen; + size_t st[JSON_MAX]; + int mime = ms->flags & MAGIC_MIME; + + + if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0) + return 0; + + memset(st, 0, sizeof(st)); + + if (!json_parse(&uc, ue, st, 0)) + return 0; + + if (mime == MAGIC_MIME_ENCODING) + return 1; + if (mime) { + if (file_printf(ms, "application/json") == -1) + return -1; + return 1; + } + if (file_printf(ms, "JSON data") == -1) + return -1; +#if JSON_COUNT +#define P(n) st[n], st[n] > 1 ? "s" : "" + if (file_printf(ms, " (%" SIZE_T_FORMAT "u object%s, %" SIZE_T_FORMAT + "u array%s, %" SIZE_T_FORMAT "u string%s, %" SIZE_T_FORMAT + "u constant%s, %" SIZE_T_FORMAT "u number%s)", P(JSON_OBJECT), + P(JSON_ARRAY), P(JSON_STRING), P(JSON_CONSTANT), P(JSON_NUMBER)) + == -1) + return -1; +#endif + return 1; +} + +#else + +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + int fd, rv; + struct stat st; + unsigned char *p; + size_t stats[JSON_MAX]; + + if ((fd = open(argv[1], O_RDONLY)) == -1) + err(EXIT_FAILURE, "Can't open `%s'", argv[1]); + + if (fstat(fd, &st) == -1) + err(EXIT_FAILURE, "Can't stat `%s'", argv[1]); + + if ((p = malloc(st.st_size)) == NULL) + err(EXIT_FAILURE, "Can't allocate %jd bytes", + (intmax_t)st.st_size); + if (read(fd, p, st.st_size) != st.st_size) + err(EXIT_FAILURE, "Can't read %jd bytes", + (intmax_t)st.st_size); + memset(stats, 0, sizeof(stats)); + printf("is json %d\n", json_parse((const unsigned char **)&p, + p + st.st_size, stats, 0)); + return 0; +} +#endif diff --git a/libmagic/src/main/cpp/file/is_tar.c b/libmagic/src/main/cpp/file/is_tar.c index 7110604..82b0805 100644 --- a/libmagic/src/main/cpp/file/is_tar.c +++ b/libmagic/src/main/cpp/file/is_tar.c @@ -40,7 +40,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: is_tar.c,v 1.41 2017/11/02 20:25:39 christos Exp $") +FILE_RCSID("@(#)$File: is_tar.c,v 1.44 2019/02/20 02:35:27 christos Exp $") #endif #include "magic.h" @@ -62,7 +62,7 @@ static const char tartype[][32] = { /* should be equal to messages */ protected int file_is_tar(struct magic_set *ms, const struct buffer *b) { - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; /* * Do the tar test first, because if the first file in the tar @@ -78,9 +78,13 @@ file_is_tar(struct magic_set *ms, const struct buffer *b) if (tar < 1 || tar > 3) return 0; + if (mime == MAGIC_MIME_ENCODING) + return 1; + if (file_printf(ms, "%s", mime ? "application/x-tar" : tartype[tar - 1]) == -1) return -1; + return 1; } @@ -94,7 +98,8 @@ file_is_tar(struct magic_set *ms, const struct buffer *b) private int is_tar(const unsigned char *buf, size_t nbytes) { - const union record *header = (const union record *)(const void *)buf; + const union record *header = RCAST(const union record *, + RCAST(const void *, buf)); size_t i; int sum, recsum; const unsigned char *p, *ep; @@ -143,7 +148,7 @@ from_oct(const char *where, size_t digs) if (digs == 0) return -1; - while (isspace((unsigned char)*where)) { /* Skip spaces */ + while (isspace(CAST(unsigned char, *where))) { /* Skip spaces */ where++; if (digs-- == 0) return -1; /* All blank field */ @@ -154,7 +159,7 @@ from_oct(const char *where, size_t digs) digs--; } - if (digs > 0 && *where && !isspace((unsigned char)*where)) + if (digs > 0 && *where && !isspace(CAST(unsigned char, *where))) return -1; /* Ended on non-(space/NUL) */ return value; diff --git a/libmagic/src/main/cpp/file/localtime_r.c b/libmagic/src/main/cpp/file/localtime_r.c deleted file mode 100644 index 35c3b40..0000000 --- a/libmagic/src/main/cpp/file/localtime_r.c +++ /dev/null @@ -1,19 +0,0 @@ -/* $File: localtime_r.c,v 1.1 2015/01/09 19:28:32 christos Exp $ */ - -#include "file.h" -#ifndef lint -FILE_RCSID("@(#)$File: localtime_r.c,v 1.1 2015/01/09 19:28:32 christos Exp $") -#endif /* lint */ -#include -#include - -/* asctime_r is not thread-safe anyway */ -struct tm * -localtime_r(const time_t *t, struct tm *tm) -{ - struct tm *tmp = localtime(t); - if (tmp == NULL) - return NULL; - memcpy(tm, tmp, sizeof(*tm)); - return tmp; -} diff --git a/libmagic/src/main/cpp/file/magic.c b/libmagic/src/main/cpp/file/magic.c index 1448a69..2207f08 100644 --- a/libmagic/src/main/cpp/file/magic.c +++ b/libmagic/src/main/cpp/file/magic.c @@ -33,7 +33,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: magic.c,v 1.102 2017/08/28 13:39:18 christos Exp $") +FILE_RCSID("@(#)$File: magic.c,v 1.109 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -44,9 +44,7 @@ FILE_RCSID("@(#)$File: magic.c,v 1.102 2017/08/28 13:39:18 christos Exp $") #ifdef QUICK #include #endif -#ifdef HAVE_LIMITS_H #include /* for PIPE_BUF */ -#endif #if defined(HAVE_UTIMES) # include @@ -314,7 +312,8 @@ magic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes, { if (ms == NULL) return -1; - return buffer_apprentice(ms, (struct magic **)bufs, sizes, nbufs); + return buffer_apprentice(ms, RCAST(struct magic **, bufs), + sizes, nbufs); } #endif @@ -407,7 +406,7 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) struct stat sb; ssize_t nbytes = 0; /* number of bytes read from a datafile */ int ispipe = 0; - off_t pos = (off_t)-1; + off_t pos = CAST(off_t, -1); if (file_reset(ms, 1) == -1) goto out; @@ -435,25 +434,13 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) if (fd == STDIN_FILENO) _setmode(STDIN_FILENO, O_BINARY); #endif - - if (inname == NULL) { - if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) - ispipe = 1; - else - pos = lseek(fd, (off_t)0, SEEK_CUR); - } else { - int flags = O_RDONLY|O_BINARY; - int okstat = stat(inname, &sb) == 0; - - if (okstat && S_ISFIFO(sb.st_mode)) { -#ifdef O_NONBLOCK - flags |= O_NONBLOCK; -#endif - ispipe = 1; - } - + if (inname != NULL) { + int flags = O_RDONLY|O_BINARY|O_NONBLOCK; errno = 0; if ((fd = open(inname, flags)) < 0) { + int okstat = stat(inname, &sb) == 0; + if (okstat && S_ISFIFO(sb.st_mode)) + ispipe = 1; #ifdef WIN32 /* * Can't stat, can't open. It may have been opened in @@ -472,12 +459,13 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) rv = 0; goto done; } -#ifdef O_NONBLOCK - if ((flags = fcntl(fd, F_GETFL)) != -1) { - flags &= ~O_NONBLOCK; - (void)fcntl(fd, F_SETFL, flags); - } -#endif + } + + if (fd != -1) { + if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) + ispipe = 1; + if (inname == NULL) + pos = lseek(fd, CAST(off_t, 0), SEEK_CUR); } /* @@ -486,8 +474,8 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) if (ispipe) { ssize_t r = 0; - while ((r = sread(fd, (void *)&buf[nbytes], - (size_t)(ms->bytes_max - nbytes), 1)) > 0) { + while ((r = sread(fd, RCAST(void *, &buf[nbytes]), + CAST(size_t, ms->bytes_max - nbytes), 1)) > 0) { nbytes += r; if (r < PIPE_BUF) break; } @@ -507,7 +495,7 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) _isatty(fd) ? 8 * 1024 : #endif ms->bytes_max; - if ((nbytes = read(fd, (char *)buf, howmany)) == -1) { + if ((nbytes = read(fd, RCAST(void *, buf), howmany)) == -1) { if (inname == NULL && fd != STDIN_FILENO) file_error(ms, errno, "cannot read fd %d", fd); else @@ -518,13 +506,13 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) } (void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */ - if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1) + if (file_buffer(ms, fd, inname, buf, CAST(size_t, nbytes)) == -1) goto done; rv = 0; done: free(buf); if (fd != -1) { - if (pos != (off_t)-1) + if (pos != CAST(off_t, -1)) (void)lseek(fd, pos, SEEK_SET); close_and_restore(ms, inname, fd, &sb); } @@ -598,27 +586,29 @@ magic_version(void) public int magic_setparam(struct magic_set *ms, int param, const void *val) { + if (ms == NULL) + return -1; switch (param) { case MAGIC_PARAM_INDIR_MAX: - ms->indir_max = (uint16_t)*(const size_t *)val; + ms->indir_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_NAME_MAX: - ms->name_max = (uint16_t)*(const size_t *)val; + ms->name_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_ELF_PHNUM_MAX: - ms->elf_phnum_max = (uint16_t)*(const size_t *)val; + ms->elf_phnum_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_ELF_SHNUM_MAX: - ms->elf_shnum_max = (uint16_t)*(const size_t *)val; + ms->elf_shnum_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_ELF_NOTES_MAX: - ms->elf_notes_max = (uint16_t)*(const size_t *)val; + ms->elf_notes_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_REGEX_MAX: - ms->elf_notes_max = (uint16_t)*(const size_t *)val; + ms->regex_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_BYTES_MAX: - ms->bytes_max = *(const size_t *)val; + ms->bytes_max = *CAST(const size_t *, val); return 0; default: errno = EINVAL; @@ -629,27 +619,29 @@ magic_setparam(struct magic_set *ms, int param, const void *val) public int magic_getparam(struct magic_set *ms, int param, void *val) { + if (ms == NULL) + return -1; switch (param) { case MAGIC_PARAM_INDIR_MAX: - *(size_t *)val = ms->indir_max; + *CAST(size_t *, val) = ms->indir_max; return 0; case MAGIC_PARAM_NAME_MAX: - *(size_t *)val = ms->name_max; + *CAST(size_t *, val) = ms->name_max; return 0; case MAGIC_PARAM_ELF_PHNUM_MAX: - *(size_t *)val = ms->elf_phnum_max; + *CAST(size_t *, val) = ms->elf_phnum_max; return 0; case MAGIC_PARAM_ELF_SHNUM_MAX: - *(size_t *)val = ms->elf_shnum_max; + *CAST(size_t *, val) = ms->elf_shnum_max; return 0; case MAGIC_PARAM_ELF_NOTES_MAX: - *(size_t *)val = ms->elf_notes_max; + *CAST(size_t *, val) = ms->elf_notes_max; return 0; case MAGIC_PARAM_REGEX_MAX: - *(size_t *)val = ms->regex_max; + *CAST(size_t *, val) = ms->regex_max; return 0; case MAGIC_PARAM_BYTES_MAX: - *(size_t *)val = ms->bytes_max; + *CAST(size_t *, val) = ms->bytes_max; return 0; default: errno = EINVAL; diff --git a/libmagic/src/main/cpp/file/magic.h b/libmagic/src/main/cpp/file/magic.h index 2d707d5..ac8f8e1 100644 --- a/libmagic/src/main/cpp/file/magic.h +++ b/libmagic/src/main/cpp/file/magic.h @@ -58,6 +58,7 @@ #define MAGIC_NO_CHECK_CDF 0x0040000 /* Don't check for cdf files */ #define MAGIC_NO_CHECK_TOKENS 0x0100000 /* Don't check tokens */ #define MAGIC_NO_CHECK_ENCODING 0x0200000 /* Don't check text encodings */ +#define MAGIC_NO_CHECK_JSON 0x0400000 /* Don't check for JSON files */ /* No built-in tests; only consult the magic file */ #define MAGIC_NO_CHECK_BUILTIN ( \ @@ -70,6 +71,7 @@ MAGIC_NO_CHECK_CDF | \ MAGIC_NO_CHECK_TOKENS | \ MAGIC_NO_CHECK_ENCODING | \ + MAGIC_NO_CHECK_JSON | \ 0 \ ) @@ -96,7 +98,7 @@ b\22no_check_cdf\0\ b\23no_check_reserved0\0\ b\24no_check_tokens\0\ b\25no_check_encoding\0\ -b\26no_check_reserved1\0\ +b\26no_check_json\0\ b\27no_check_reserved2\0\ b\30extension\0\ b\31transp_compression\0\ @@ -109,7 +111,7 @@ b\31transp_compression\0\ #define MAGIC_NO_CHECK_FORTRAN 0x000000 /* Don't check ascii/fortran */ #define MAGIC_NO_CHECK_TROFF 0x000000 /* Don't check ascii/troff */ -#define MAGIC_VERSION 532 /* This implementation */ +#define MAGIC_VERSION 536 /* This implementation */ #ifdef __cplusplus diff --git a/libmagic/src/main/cpp/file/mygetopt.h b/libmagic/src/main/cpp/file/mygetopt.h index ef87525..d766762 100644 --- a/libmagic/src/main/cpp/file/mygetopt.h +++ b/libmagic/src/main/cpp/file/mygetopt.h @@ -64,5 +64,5 @@ struct option { int getopt_long(int, char * const *, const char *, const struct option *, int *); - + #endif /* !_GETOPT_H_ */ diff --git a/libmagic/src/main/cpp/file/print.c b/libmagic/src/main/cpp/file/print.c index 4ffa445..6dad1de 100644 --- a/libmagic/src/main/cpp/file/print.c +++ b/libmagic/src/main/cpp/file/print.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: print.c,v 1.81 2016/01/19 15:09:03 christos Exp $") +FILE_RCSID("@(#)$File: print.c,v 1.84 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include @@ -65,7 +65,7 @@ file_mdump(struct magic *m) if (m->in_op & FILE_OPINVERSE) (void) fputc('~', stderr); (void) fprintf(stderr, "%c%u),", - ((size_t)(m->in_op & FILE_OPS_MASK) < + (CAST(size_t, m->in_op & FILE_OPS_MASK) < SZOF(optyp)) ? optyp[m->in_op & FILE_OPS_MASK] : '?', m->in_offset); } @@ -78,16 +78,16 @@ file_mdump(struct magic *m) if (IS_STRING(m->type)) { if (m->str_flags) { (void) fputc('/', stderr); - if (m->str_flags & STRING_COMPACT_WHITESPACE) + if (m->str_flags & STRING_COMPACT_WHITESPACE) (void) fputc(CHAR_COMPACT_WHITESPACE, stderr); - if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE) + if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE) (void) fputc(CHAR_COMPACT_OPTIONAL_WHITESPACE, stderr); - if (m->str_flags & STRING_IGNORE_LOWERCASE) + if (m->str_flags & STRING_IGNORE_LOWERCASE) (void) fputc(CHAR_IGNORE_LOWERCASE, stderr); - if (m->str_flags & STRING_IGNORE_UPPERCASE) + if (m->str_flags & STRING_IGNORE_UPPERCASE) (void) fputc(CHAR_IGNORE_UPPERCASE, stderr); - if (m->str_flags & REGEX_OFFSET_START) + if (m->str_flags & REGEX_OFFSET_START) (void) fputc(CHAR_REGEX_OFFSET_START, stderr); if (m->str_flags & STRING_TEXTTEST) (void) fputc(CHAR_TEXTTEST, stderr); @@ -112,14 +112,14 @@ file_mdump(struct magic *m) (void) fprintf(stderr, "/%u", m->str_range); } else { - if ((size_t)(m->mask_op & FILE_OPS_MASK) < SZOF(optyp)) + if (CAST(size_t, m->mask_op & FILE_OPS_MASK) < SZOF(optyp)) (void) fputc(optyp[m->mask_op & FILE_OPS_MASK], stderr); else (void) fputc('?', stderr); - + if (m->num_mask) { (void) fprintf(stderr, "%.8llx", - (unsigned long long)m->num_mask); + CAST(unsigned long long, m->num_mask)); } } (void) fprintf(stderr, ",%c", m->reln); @@ -141,7 +141,7 @@ file_mdump(struct magic *m) case FILE_LEQUAD: case FILE_QUAD: (void) fprintf(stderr, "%" INT64_T_FORMAT "d", - (unsigned long long)m->value.q); + CAST(long long, m->value.q)); break; case FILE_PSTRING: case FILE_STRING: @@ -149,7 +149,8 @@ file_mdump(struct magic *m) case FILE_BESTRING16: case FILE_LESTRING16: case FILE_SEARCH: - file_showstr(stderr, m->value.s, (size_t)m->vallen); + file_showstr(stderr, m->value.s, + CAST(size_t, m->vallen)); break; case FILE_DATE: case FILE_LEDATE: @@ -217,11 +218,11 @@ file_magwarn(struct magic_set *ms, const char *f, ...) va_list va; /* cuz we use stdout for most, stderr here */ - (void) fflush(stdout); + (void) fflush(stdout); if (ms->file) (void) fprintf(stderr, "%s, %lu: ", ms->file, - (unsigned long)ms->line); + CAST(unsigned long, ms->line)); (void) fprintf(stderr, "Warning: "); va_start(va, f); (void) vfprintf(stderr, f, va); @@ -243,7 +244,7 @@ file_fmttime(uint64_t v, int flags, char *buf) } else { // XXX: perhaps detect and print something if overflow // on 32 bit time_t? - t = (time_t)v; + t = CAST(time_t, v); } if (flags & FILE_T_LOCAL) { diff --git a/libmagic/src/main/cpp/file/readcdf.c b/libmagic/src/main/cpp/file/readcdf.c index 4b86e6f..5fa98e8 100644 --- a/libmagic/src/main/cpp/file/readcdf.c +++ b/libmagic/src/main/cpp/file/readcdf.c @@ -26,7 +26,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readcdf.c,v 1.67 2018/04/15 19:57:07 christos Exp $") +FILE_RCSID("@(#)$File: readcdf.c,v 1.72 2019/02/20 02:35:27 christos Exp $") #endif #include @@ -204,7 +204,7 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, && len--; s += k) { if (*s == '\0') break; - if (isprint((unsigned char)*s)) + if (isprint(CAST(unsigned char, *s))) vbuf[j++] = *s; } if (j == sizeof(vbuf)) @@ -252,7 +252,7 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, return -1; } } - if (!NOTMIME(ms)) { + if (ms->flags & MAGIC_MIME_TYPE) { if (str == NULL) return 0; if (file_printf(ms, "application/%s", str) == -1) @@ -285,7 +285,7 @@ cdf_file_catalog(struct magic_set *ms, const cdf_header_t *h, return -1; } free(cat); - } else { + } else if (ms->flags & MAGIC_MIME_TYPE) { if (file_printf(ms, "application/CDFV2") == -1) return -1; } @@ -318,19 +318,19 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, case 2: if (file_printf(ms, ", Os: Windows, Version %d.%d", si.si_os_version & 0xff, - (uint32_t)si.si_os_version >> 8) == -1) + CAST(uint32_t, si.si_os_version) >> 8) == -1) return -2; break; case 1: if (file_printf(ms, ", Os: MacOS, Version %d.%d", - (uint32_t)si.si_os_version >> 8, + CAST(uint32_t, si.si_os_version) >> 8, si.si_os_version & 0xff) == -1) return -2; break; default: if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, si.si_os_version & 0xff, - (uint32_t)si.si_os_version >> 8) == -1) + CAST(uint32_t, si.si_os_version) >> 8) == -1) return -2; break; } @@ -353,11 +353,11 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, #ifdef notdef private char * format_clsid(char *buf, size_t len, const uint64_t uuid[2]) { - snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" + snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.12" PRIx64, (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffULL, (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffULL, - (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffULL, + (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffULL, (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffULL, (uuid[1] >> 0) & (uint64_t)0x0000fffffffffffffULL); return buf; @@ -406,7 +406,7 @@ cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info, for (j = 0; str == NULL && j < dir->dir_len; j++) { d = &dir->dir_tab[j]; for (k = 0; k < sizeof(name); k++) - name[k] = (char)cdf_tole2(d->d_name[k]); + name[k] = CAST(char, cdf_tole2(d->d_name[k])); str = cdf_app_to_mime(name, NOTMIME(ms) ? name2desc : name2mime); } @@ -416,7 +416,7 @@ cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info, return -1; i = 1; } - } else { + } else if (ms->flags & MAGIC_MIME_TYPE) { if (str == NULL) str = "vnd.ms-office"; if (file_printf(ms, "application/%s", str) == -1) @@ -436,7 +436,7 @@ private struct sinfo { const char *sections[5]; const int types[5]; } sectioninfo[] = { - { "Encrypted", "encrypted", + { "Encrypted", "encrypted", { "EncryptedPackage", "EncryptedSummary", NULL, NULL, NULL, @@ -448,7 +448,7 @@ private struct sinfo { }, }, - { "QuickBooks", "quickbooks", + { "QuickBooks", "quickbooks", { #if 0 "TaxForms", "PDFTaxForms", "modulesInBackup", @@ -527,7 +527,7 @@ cdf_file_dir_info(struct magic_set *ms, const cdf_dir_t *dir) if (NOTMIME(ms)) { if (file_printf(ms, "CDFV2 %s", si->name) == -1) return -1; - } else { + } else if (ms->flags & MAGIC_MIME_TYPE) { if (file_printf(ms, "application/%s", si->mime) == -1) return -1; } @@ -540,7 +540,7 @@ protected int file_trycdf(struct magic_set *ms, const struct buffer *b) { int fd = b->fd; - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; cdf_info_t info; cdf_header_t h; @@ -614,7 +614,7 @@ file_trycdf(struct magic_set *ms, const struct buffer *b) if (file_printf(ms, "Hangul (Korean) Word Processor File 5.x") == -1) return -1; - } else { + } else if (ms->flags & MAGIC_MIME_TYPE) { if (file_printf(ms, "application/x-hwp") == -1) return -1; } @@ -661,19 +661,20 @@ file_trycdf(struct magic_set *ms, const struct buffer *b) out1: free(sat.sat_tab); out0: - if (i == -1) { - if (NOTMIME(ms)) { + /* If we handled it already, return */ + if (i != -1) + return i; + /* Provide a default handler */ + if (NOTMIME(ms)) { if (file_printf(ms, "Composite Document File V2 Document") == -1) - return -1; - if (*expn) - if (file_printf(ms, ", %s", expn) == -1) return -1; - } else { + if (*expn) + if (file_printf(ms, ", %s", expn) == -1) + return -1; + } else if (ms->flags & MAGIC_MIME_TYPE) { if (file_printf(ms, "application/CDFV2") == -1) - return -1; - } - i = 1; + return -1; } - return i; + return 1; } diff --git a/libmagic/src/main/cpp/file/readelf.c b/libmagic/src/main/cpp/file/readelf.c index db0b35a..db43c6c 100644 --- a/libmagic/src/main/cpp/file/readelf.c +++ b/libmagic/src/main/cpp/file/readelf.c @@ -1,7 +1,7 @@ /* * Copyright (c) Christos Zoulas 2003. * All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readelf.c,v 1.144 2018/07/08 23:37:33 christos Exp $") +FILE_RCSID("@(#)$File: readelf.c,v 1.162 2019/02/20 02:35:27 christos Exp $") #endif #ifdef BUILTIN_ELF @@ -69,7 +69,7 @@ toomany(struct magic_set *ms, const char *name, uint16_t num) { if (file_printf(ms, ", too many %s (%u)", name, num) == -1) return -1; - return 0; + return 1; } private uint16_t @@ -85,7 +85,7 @@ getu16(int swap, uint16_t value) retval.c[0] = tmpval.c[1]; retval.c[1] = tmpval.c[0]; - + return retval.ui; } else return value; @@ -106,7 +106,7 @@ getu32(int swap, uint32_t value) retval.c[1] = tmpval.c[2]; retval.c[2] = tmpval.c[1]; retval.c[3] = tmpval.c[0]; - + return retval.ui; } else return value; @@ -131,7 +131,7 @@ getu64(int swap, uint64_t value) retval.c[5] = tmpval.c[2]; retval.c[6] = tmpval.c[1]; retval.c[7] = tmpval.c[0]; - + return retval.ui; } else return value; @@ -262,7 +262,10 @@ static const size_t prpsoffsets32[] = { 84, /* SunOS 5.x (short name) */ 44, /* Linux (command line) */ - 28, /* Linux 2.0.36 (short name) */ + 28, /* Linux (short name) */ + + 48, /* Linux PowerPC (command line) */ + 32, /* Linux PowerPC (short name) */ 8, /* FreeBSD */ }; @@ -352,6 +355,11 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, off_t ph_off = off; int ph_num = num; + if (num == 0) { + if (file_printf(ms, ", no program header") == -1) + return -1; + return 0; + } if (size != xph_sizeof) { if (file_printf(ms, ", corrupted program header size") == -1) return -1; @@ -388,9 +396,9 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, } offset = 0; for (;;) { - if (offset >= (size_t)bufsize) + if (offset >= CAST(size_t, bufsize)) break; - offset = donote(ms, nbuf, offset, (size_t)bufsize, + offset = donote(ms, nbuf, offset, CAST(size_t, bufsize), clazz, swap, 4, flags, notecount, fd, ph_off, ph_num, fsize); if (offset == 0) @@ -461,25 +469,25 @@ do_note_freebsd_version(struct magic_set *ms, int swap, void *v) * Contents is __FreeBSD_version, whose relation to OS * versions is defined by a huge table in the Porter's * Handbook. This is the general scheme: - * + * * Releases: * Mmp000 (before 4.10) * Mmi0p0 (before 5.0) * Mmm0p0 - * + * * Development branches: * Mmpxxx (before 4.6) * Mmp1xx (before 4.10) * Mmi1xx (before 5.0) * M000xx (pre-M.0) * Mmm1xx - * + * * M = major version * m = minor version * i = minor version increment (491000 -> 4.10) * p = patchlevel * x = revision - * + * * The first release of FreeBSD to use ELF by default * was version 3.0. */ @@ -528,7 +536,7 @@ do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz, size_t noff, size_t doff, int *flags) { - if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && + if (namesz == 4 && strcmp(RCAST(char *, &nbuf[noff]), "GNU") == 0 && type == NT_GNU_BUILD_ID && (descsz >= 4 && descsz <= 20)) { uint8_t desc[20]; const char *btype; @@ -556,11 +564,11 @@ do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, return 1; return 1; } - if (namesz == 4 && strcmp((char *)&nbuf[noff], "Go") == 0 && + if (namesz == 4 && strcmp(RCAST(char *, &nbuf[noff]), "Go") == 0 && type == NT_GO_BUILD_ID && descsz < 128) { - if (file_printf(ms, ", Go BuildID=%s", - (char *)&nbuf[doff]) == -1) - return 1; + if (file_printf(ms, ", Go BuildID=%.*s", + CAST(int, descsz), RCAST(char *, &nbuf[doff])) == -1) + return -1; return 1; } return 0; @@ -571,14 +579,18 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, int swap, uint32_t namesz, uint32_t descsz, size_t noff, size_t doff, int *flags) { - if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 && - type == NT_GNU_VERSION && descsz == 2) { - *flags |= FLAGS_DID_OS_NOTE; - file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]); + const char *name = RCAST(const char *, &nbuf[noff]); + + if (namesz == 5 && strcmp(name, "SuSE") == 0 && + type == NT_GNU_VERSION && descsz == 2) { + *flags |= FLAGS_DID_OS_NOTE; + if (file_printf(ms, ", for SuSE %d.%d", nbuf[doff], + nbuf[doff + 1]) == -1) + return -1; return 1; } - if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && + if (namesz == 4 && strcmp(name, "GNU") == 0 && type == NT_GNU_VERSION && descsz == 16) { uint32_t desc[4]; memcpy(desc, &nbuf[doff], sizeof(desc)); @@ -609,7 +621,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, break; default: if (file_printf(ms, "") == -1) - return 1; + return 1; } if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]), elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1) @@ -617,7 +629,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, return 1; } - if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { + if (namesz == 7 && strcmp(name, "NetBSD") == 0) { if (type == NT_NETBSD_VERSION && descsz == 4) { *flags |= FLAGS_DID_OS_NOTE; do_note_netbsd_version(ms, swap, &nbuf[doff]); @@ -625,7 +637,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, } } - if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { + if (namesz == 8 && strcmp(name, "FreeBSD") == 0) { if (type == NT_FREEBSD_VERSION && descsz == 4) { *flags |= FLAGS_DID_OS_NOTE; do_note_freebsd_version(ms, swap, &nbuf[doff]); @@ -633,7 +645,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, } } - if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && + if (namesz == 8 && strcmp(name, "OpenBSD") == 0 && type == NT_OPENBSD_VERSION && descsz == 4) { *flags |= FLAGS_DID_OS_NOTE; if (file_printf(ms, ", for OpenBSD") == -1) @@ -642,7 +654,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, return 1; } - if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && + if (namesz == 10 && strcmp(name, "DragonFly") == 0 && type == NT_DRAGONFLY_VERSION && descsz == 4) { uint32_t desc; *flags |= FLAGS_DID_OS_NOTE; @@ -663,7 +675,9 @@ do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, int swap, uint32_t namesz, uint32_t descsz, size_t noff, size_t doff, int *flags) { - if (namesz == 4 && strcmp((char *)&nbuf[noff], "PaX") == 0 && + const char *name = RCAST(const char *, &nbuf[noff]); + + if (namesz == 4 && strcmp(name, "PaX") == 0 && type == NT_NETBSD_PAX && descsz == 4) { static const char *pax[] = { "+mprotect", @@ -685,7 +699,7 @@ do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, return 1; for (i = 0; i < __arraycount(pax); i++) { - if (((1 << (int)i) & desc) == 0) + if (((1 << CAST(int, i)) & desc) == 0) continue; if (file_printf(ms, "%s%s", did++ ? "," : "", pax[i]) == -1) @@ -702,6 +716,8 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, size_t noff, size_t doff, int *flags, size_t size, int clazz) { #ifdef ELFCORE + const char *name = RCAST(const char *, &nbuf[noff]); + int os_style = -1; /* * Sigh. The 2.0.36 kernel in Debian 2.1, at @@ -717,16 +733,16 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, * doesn't include the terminating null in the * name.... */ - if ((namesz == 4 && strncmp((char *)&nbuf[noff], "CORE", 4) == 0) || - (namesz == 5 && strcmp((char *)&nbuf[noff], "CORE") == 0)) { + if ((namesz == 4 && strncmp(name, "CORE", 4) == 0) || + (namesz == 5 && strcmp(name, "CORE") == 0)) { os_style = OS_STYLE_SVR4; - } + } - if ((namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) { + if ((namesz == 8 && strcmp(name, "FreeBSD") == 0)) { os_style = OS_STYLE_FREEBSD; } - if ((namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11) + if ((namesz >= 11 && strncmp(name, "NetBSD-CORE", 11) == 0)) { os_style = OS_STYLE_NETBSD; } @@ -745,17 +761,17 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, char sbuf[512]; struct NetBSD_elfcore_procinfo pi; memset(&pi, 0, sizeof(pi)); - memcpy(&pi, nbuf + doff, descsz); + memcpy(&pi, nbuf + doff, MIN(descsz, sizeof(pi))); if (file_printf(ms, ", from '%.31s', pid=%u, uid=%u, " "gid=%u, nlwps=%u, lwp=%u (signal %u/code %u)", file_printable(sbuf, sizeof(sbuf), - CAST(char *, pi.cpi_name)), - elf_getu32(swap, (uint32_t)pi.cpi_pid), + RCAST(char *, pi.cpi_name), sizeof(pi.cpi_name)), + elf_getu32(swap, CAST(uint32_t, pi.cpi_pid)), elf_getu32(swap, pi.cpi_euid), elf_getu32(swap, pi.cpi_egid), elf_getu32(swap, pi.cpi_nlwps), - elf_getu32(swap, (uint32_t)pi.cpi_siglwp), + elf_getu32(swap, CAST(uint32_t, pi.cpi_siglwp)), elf_getu32(swap, pi.cpi_signo), elf_getu32(swap, pi.cpi_sigcode)) == -1) return 1; @@ -765,6 +781,28 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, } break; + case OS_STYLE_FREEBSD: + if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { + size_t argoff, pidoff; + + if (clazz == ELFCLASS32) + argoff = 4 + 4 + 17; + else + argoff = 4 + 4 + 8 + 17; + if (file_printf(ms, ", from '%.80s'", nbuf + doff + + argoff) == -1) + return 1; + pidoff = argoff + 81 + 2; + if (doff + pidoff + 4 <= size) { + if (file_printf(ms, ", pid=%u", + elf_getu32(swap, *RCAST(uint32_t *, (nbuf + + doff + pidoff)))) == -1) + return 1; + } + *flags |= FLAGS_DID_CORE; + } + break; + default: if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { size_t i, j; @@ -847,8 +885,8 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, i = k; } - cname = (unsigned char *) - &nbuf[doff + prpsoffsets(i)]; + cname = CAST(unsigned char *, + &nbuf[doff + prpsoffsets(i)]); for (cp = cname; cp < nbuf + size && *cp && isprint(*cp); cp++) continue; @@ -859,7 +897,7 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, while (cp > cname && isspace(cp[-1])) cp--; if (file_printf(ms, ", from '%.*s'", - (int)(cp - cname), cname) == -1) + CAST(int, cp - cname), cname) == -1) return 1; *flags |= FLAGS_DID_CORE; return 1; @@ -886,7 +924,8 @@ get_offset_from_virtaddr(struct magic_set *ms, int swap, int clazz, int fd, * virtual address in which the "virtaddr" belongs to. */ for ( ; num; num--) { - if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { + if (pread(fd, xph_addr, xph_sizeof, off) < + CAST(ssize_t, xph_sizeof)) { file_badread(ms); return -1; } @@ -916,7 +955,8 @@ get_string_on_virtaddr(struct magic_set *ms, offset = get_offset_from_virtaddr(ms, swap, clazz, fd, ph_off, ph_num, fsize, virtaddr); - if ((buflen = pread(fd, buf, CAST(size_t, buflen), offset)) <= 0) { + if (offset < 0 || + (buflen = pread(fd, buf, CAST(size_t, buflen), offset)) <= 0) { file_badread(ms); return 0; } @@ -925,7 +965,7 @@ get_string_on_virtaddr(struct magic_set *ms, /* We expect only printable characters, so return if buffer contains * non-printable character before the '\0' or just '\0'. */ - for (bptr = buf; *bptr && isprint((unsigned char)*bptr); bptr++) + for (bptr = buf; *bptr && isprint(CAST(unsigned char, *bptr)); bptr++) continue; if (*bptr != '\0') return 0; @@ -1027,12 +1067,12 @@ do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, if (buflen == 0) continue; - + if (file_printf(ms, ", %s: '%s'", tag, buf) == -1) return 0; } else { - if (file_printf(ms, ", %s: %d", tag, (int) xauxv_val) - == -1) + if (file_printf(ms, ", %s: %d", tag, + CAST(int, xauxv_val)) == -1) return 0; } } @@ -1062,7 +1102,7 @@ dodynamic(struct magic_set *ms, void *vbuf, size_t offset, size_t size, switch (xdh_tag) { case DT_FLAGS_1: - if (xdh_val == DF_1_PIE) + if (xdh_val & DF_1_PIE) ms->mode |= 0111; else ms->mode &= ~0111; @@ -1110,14 +1150,16 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, } if (namesz & 0x80000000) { - file_printf(ms, ", bad note name size %#lx", - CAST(unsigned long, namesz)); + if (file_printf(ms, ", bad note name size %#lx", + CAST(unsigned long, namesz)) == -1) + return 0; return 0; } if (descsz & 0x80000000) { - file_printf(ms, ", bad note description size %#lx", - CAST(unsigned long, descsz)); + if (file_printf(ms, ", bad note description size %#lx", + CAST(unsigned long, descsz)) == -1) + return 0; return 0; } @@ -1151,7 +1193,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, namesz, descsz, noff, doff, flags)) return offset; } - + if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) { if (do_pax_note(ms, nbuf, xnh_type, swap, namesz, descsz, noff, doff, flags)) @@ -1171,7 +1213,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, return offset; } - if (namesz == 7 && strcmp(CAST(char *, &nbuf[noff]), "NetBSD") == 0) { + if (namesz == 7 && strcmp(RCAST(char *, &nbuf[noff]), "NetBSD") == 0) { int descw, flag; const char *str, *tag; if (descsz > 100) @@ -1202,7 +1244,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, if (*flags & flag) return offset; - str = CAST(const char *, &nbuf[doff]); + str = RCAST(const char *, &nbuf[doff]); descw = CAST(int, descsz); *flags |= flag; file_printf(ms, ", %s: %.*s", tag, descw, str); @@ -1278,6 +1320,11 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, char name[50]; ssize_t namesize; + if (num == 0) { + if (file_printf(ms, ", no section header") == -1) + return -1; + return 0; + } if (size != xsh_sizeof) { if (file_printf(ms, ", corrupted section header size") == -1) return -1; @@ -1343,7 +1390,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, CAST(uintmax_t, xsh_size), CAST(uintmax_t, fsize)) == -1) return -1; - return 0; + return 0; } if ((nbuf = malloc(xsh_size)) == NULL) { file_error(ms, errno, "Cannot allocate memory" @@ -1428,7 +1475,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, return -1; break; } - // gnu attributes + // gnu attributes #endif break; } @@ -1548,7 +1595,12 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, char interp[BUFSIZ]; ssize_t bufsize; size_t offset, align, len; - + + if (num == 0) { + if (file_printf(ms, ", no program header") == -1) + return -1; + return 0; + } if (size != xph_sizeof) { if (file_printf(ms, ", corrupted program header size") == -1) return -1; @@ -1558,7 +1610,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, interp[0] = '\0'; for ( ; num; num--) { int doread; - if (pread(fd, xph_addr, xph_sizeof, off) < + if (pread(fd, xph_addr, xph_sizeof, off) < CAST(ssize_t, xph_sizeof)) { file_badread(ms); return -1; @@ -1579,7 +1631,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, continue; if (((align = xph_align) & 0x80000000UL) != 0 || align < 4) { - if (file_printf(ms, + if (file_printf(ms, ", invalid note alignment %#lx", CAST(unsigned long, align)) == -1) return -1; @@ -1613,8 +1665,10 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, switch (xph_type) { case PT_DYNAMIC: offset = 0; + // Let DF_1 determine if we are PIE or not. + ms->mode &= ~0111; for (;;) { - if (offset >= (size_t)bufsize) + if (offset >= CAST(size_t, bufsize)) break; offset = dodynamic(ms, nbuf, offset, CAST(size_t, bufsize), clazz, swap); @@ -1626,7 +1680,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, case PT_INTERP: if (bufsize && nbuf[0]) { nbuf[bufsize - 1] = '\0'; - memcpy(interp, nbuf, bufsize); + memcpy(interp, nbuf, CAST(size_t, bufsize)); } else strlcpy(interp, "*empty*", sizeof(interp)); break; @@ -1637,7 +1691,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, */ offset = 0; for (;;) { - if (offset >= (size_t)bufsize) + if (offset >= CAST(size_t, bufsize)) break; offset = donote(ms, nbuf, offset, CAST(size_t, bufsize), clazz, swap, align, @@ -1655,7 +1709,8 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, return -1; if (interp[0]) if (file_printf(ms, ", interpreter %s", - file_printable(ibuf, sizeof(ibuf), interp)) == -1) + file_printable(ibuf, sizeof(ibuf), interp, sizeof(interp))) + == -1) return -1; return 0; } @@ -1665,7 +1720,7 @@ protected int file_tryelf(struct magic_set *ms, const struct buffer *b) { int fd = b->fd; - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; union { int32_t l; @@ -1687,7 +1742,8 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) * file locations and thus file(1) cannot determine it from easily. * Instead we traverse thru all section headers until a symbol table * one is found or else the binary is stripped. - * Return immediately if it's not ELF (so we avoid pipe2file unless needed). + * Return immediately if it's not ELF (so we avoid pipe2file unless + * needed). */ if (buf[EI_MAG0] != ELFMAG0 || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1) @@ -1701,7 +1757,7 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) && (errno == ESPIPE)) fd = file_pipe2file(ms, fd, buf, nbytes); - if (fstat(fd, &st) == -1) { + if (fd == -1 || fstat(fd, &st) == -1) { file_badread(ms); return -1; } diff --git a/libmagic/src/main/cpp/file/readelf.h b/libmagic/src/main/cpp/file/readelf.h index 6ae63f2..809d3f7 100644 --- a/libmagic/src/main/cpp/file/readelf.h +++ b/libmagic/src/main/cpp/file/readelf.h @@ -1,7 +1,7 @@ /* * Copyright (c) Christos Zoulas 2003. * All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -304,7 +304,7 @@ typedef struct { #define GNU_OS_KNETBSD 4 /* - * GNU Hardware capability information + * GNU Hardware capability information * word[0]: Number of entries * word[1]: Bitmask of enabled entries * Followed by a byte id, and a NUL terminated string per entry @@ -313,7 +313,7 @@ typedef struct { /* * GNU Build ID generated by ld - * 160 bit SHA1 [default] + * 160 bit SHA1 [default] * 128 bit md5 or uuid */ #define NT_GNU_BUILD_ID 3 diff --git a/libmagic/src/main/cpp/file/seccomp.c b/libmagic/src/main/cpp/file/seccomp.c index a5abb4a..e7829ff 100644 --- a/libmagic/src/main/cpp/file/seccomp.c +++ b/libmagic/src/main/cpp/file/seccomp.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: seccomp.c,v 1.6 2018/06/26 20:29:29 christos Exp $") +FILE_RCSID("@(#)$File: seccomp.c,v 1.7 2018/09/09 20:33:28 christos Exp $") #endif /* lint */ #if HAVE_LIBSECCOMP @@ -126,14 +126,14 @@ enable_sandbox_basic(void) DENY_RULE (socket); // ... - + // applying filter... if (seccomp_load (ctx) == -1) goto out; // free ctx after the filter has been loaded into the kernel seccomp_release(ctx); return 0; - + out: seccomp_release(ctx); return -1; @@ -151,7 +151,7 @@ enable_sandbox_full(void) if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) return -1; - + // initialize the filter ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) @@ -163,10 +163,10 @@ enable_sandbox_full(void) ALLOW_RULE(dup2); ALLOW_RULE(exit); ALLOW_RULE(exit_group); - ALLOW_RULE(fcntl); - ALLOW_RULE(fcntl64); + ALLOW_RULE(fcntl); + ALLOW_RULE(fcntl64); ALLOW_RULE(fstat); - ALLOW_RULE(fstat64); + ALLOW_RULE(fstat64); ALLOW_RULE(getdents); #ifdef __NR_getdents64 ALLOW_RULE(getdents64); diff --git a/libmagic/src/main/cpp/file/softmagic.c b/libmagic/src/main/cpp/file/softmagic.c index 9a5db9d..cfc1781 100644 --- a/libmagic/src/main/cpp/file/softmagic.c +++ b/libmagic/src/main/cpp/file/softmagic.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: softmagic.c,v 1.262 2018/06/22 20:39:50 christos Exp $") +FILE_RCSID("@(#)$File: softmagic.c,v 1.278 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -45,11 +45,11 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.262 2018/06/22 20:39:50 christos Exp $") private int match(struct magic_set *, struct magic *, uint32_t, const struct buffer *, size_t, int, int, int, uint16_t *, - uint16_t *, int *, int *, int *); + uint16_t *, int *, int *, int *, int *); private int mget(struct magic_set *, struct magic *, const struct buffer *, - const unsigned char *, size_t, + const unsigned char *, size_t, size_t, unsigned int, int, int, int, uint16_t *, - uint16_t *, int *, int *, int *); + uint16_t *, int *, int *, int *, int *); private int msetoffset(struct magic_set *, struct magic *, struct buffer *, const struct buffer *, size_t, unsigned int); private int magiccheck(struct magic_set *, struct magic *); @@ -67,24 +67,46 @@ private int cvt_16(union VALUETYPE *, const struct magic *); private int cvt_32(union VALUETYPE *, const struct magic *); private int cvt_64(union VALUETYPE *, const struct magic *); -#define OFFSET_OOB(n, o, i) ((n) < (uint32_t)(o) || (i) > ((n) - (o))) -#define BE64(p) (((uint64_t)(p)->hq[0]<<56)|((uint64_t)(p)->hq[1]<<48)| \ - ((uint64_t)(p)->hq[2]<<40)|((uint64_t)(p)->hq[3]<<32)| \ - ((uint64_t)(p)->hq[4]<<24)|((uint64_t)(p)->hq[5]<<16)| \ - ((uint64_t)(p)->hq[6]<<8)|((uint64_t)(p)->hq[7])) -#define LE64(p) (((uint64_t)(p)->hq[7]<<56)|((uint64_t)(p)->hq[6]<<48)| \ - ((uint64_t)(p)->hq[5]<<40)|((uint64_t)(p)->hq[4]<<32)| \ - ((uint64_t)(p)->hq[3]<<24)|((uint64_t)(p)->hq[2]<<16)| \ - ((uint64_t)(p)->hq[1]<<8)|((uint64_t)(p)->hq[0])) -#define LE32(p) (((uint32_t)(p)->hl[3]<<24)|((uint32_t)(p)->hl[2]<<16)| \ - ((uint32_t)(p)->hl[1]<<8)|((uint32_t)(p)->hl[0])) -#define BE32(p) (((uint32_t)(p)->hl[0]<<24)|((uint32_t)(p)->hl[1]<<16)| \ - ((uint32_t)(p)->hl[2]<<8)|((uint32_t)(p)->hl[3])) -#define ME32(p) (((uint32_t)(p)->hl[1]<<24)|((uint32_t)(p)->hl[0]<<16)| \ - ((uint32_t)(p)->hl[3]<<8)|((uint32_t)(p)->hl[2])) -#define BE16(p) (((uint16_t)(p)->hs[0]<<8)|((uint16_t)(p)->hs[1])) -#define LE16(p) (((uint16_t)(p)->hs[1]<<8)|((uint16_t)(p)->hs[0])) -#define SEXT(s,v,p) ((s)?(intmax_t)(int##v##_t)(p):(intmax_t)(uint##v##_t)(p)) +#define OFFSET_OOB(n, o, i) ((n) < CAST(uint32_t, (o)) || (i) > ((n) - (o))) +#define BE64(p) ( \ + (CAST(uint64_t, (p)->hq[0])<<56)| \ + (CAST(uint64_t, (p)->hq[1])<<48)| \ + (CAST(uint64_t, (p)->hq[2])<<40)| \ + (CAST(uint64_t, (p)->hq[3])<<32)| \ + (CAST(uint64_t, (p)->hq[4])<<24)| \ + (CAST(uint64_t, (p)->hq[5])<<16)| \ + (CAST(uint64_t, (p)->hq[6])<<8)| \ + (CAST(uint64_t, (p)->hq[7]))) +#define LE64(p) ( \ + (CAST(uint64_t, (p)->hq[7])<<56)| \ + (CAST(uint64_t, (p)->hq[6])<<48)| \ + (CAST(uint64_t, (p)->hq[5])<<40)| \ + (CAST(uint64_t, (p)->hq[4])<<32)| \ + (CAST(uint64_t, (p)->hq[3])<<24)| \ + (CAST(uint64_t, (p)->hq[2])<<16)| \ + (CAST(uint64_t, (p)->hq[1])<<8)| \ + (CAST(uint64_t, (p)->hq[0]))) +#define LE32(p) ( \ + (CAST(uint32_t, (p)->hl[3])<<24)| \ + (CAST(uint32_t, (p)->hl[2])<<16)| \ + (CAST(uint32_t, (p)->hl[1])<<8)| \ + (CAST(uint32_t, (p)->hl[0]))) +#define BE32(p) ( \ + (CAST(uint32_t, (p)->hl[0])<<24)| \ + (CAST(uint32_t, (p)->hl[1])<<16)| \ + (CAST(uint32_t, (p)->hl[2])<<8)| \ + (CAST(uint32_t, (p)->hl[3]))) +#define ME32(p) ( \ + (CAST(uint32_t, (p)->hl[1])<<24)| \ + (CAST(uint32_t, (p)->hl[0])<<16)| \ + (CAST(uint32_t, (p)->hl[3])<<8)| \ + (CAST(uint32_t, (p)->hl[2]))) + +#define BE16(p) ((CAST(uint16_t, (p)->hs[0])<<8)|(CAST(uint16_t, (p)->hs[1]))) +#define LE16(p) ((CAST(uint16_t, (p)->hs[1])<<8)|(CAST(uint16_t, (p)->hs[0]))) +#define SEXT(s,v,p) ((s) ? \ + CAST(intmax_t, CAST(int##v##_t, p)) : \ + CAST(intmax_t, CAST(uint##v##_t, p))) /* * softmagic - lookup one file in parsed, in-memory copy of database @@ -111,7 +133,7 @@ file_softmagic(struct magic_set *ms, const struct buffer *b, for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) if ((rv = match(ms, ml->magic, ml->nmagic, b, 0, mode, text, 0, indir_count, name_count, - &printed_something, &need_separator, NULL)) != 0) + &printed_something, &need_separator, NULL, NULL)) != 0) return rv; return 0; @@ -167,17 +189,25 @@ private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, const struct buffer *b, size_t offset, int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count, - int *printed_something, int *need_separator, int *returnval) + int *printed_something, int *need_separator, int *returnval, + int *found_match) { uint32_t magindex = 0; unsigned int cont_level = 0; - int returnvalv = 0, e; /* if a match is found it is set to 1*/ + int found_matchv = 0; /* if a match is found it is set to 1*/ + int returnvalv = 0, e; int firstline = 1; /* a flag to print X\n X\n- X */ struct buffer bb; int print = (ms->flags & MAGIC_NODESC) == 0; + /* + * returnval can be 0 if a match is found, but there was no + * annotation to be printed. + */ if (returnval == NULL) returnval = &returnvalv; + if (found_match == NULL) + found_match = &found_matchv; if (file_check_mem(ms, cont_level) == -1) return -1; @@ -206,17 +236,21 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, ms->line = m->lineno; /* if main entry matches, print it... */ - switch (mget(ms, m, b, bb.fbuf, bb.flen, offset, cont_level, + switch (mget(ms, m, b, CAST(const unsigned char *, bb.fbuf), + bb.flen, offset, cont_level, mode, text, flip, indir_count, name_count, - printed_something, need_separator, returnval)) { + printed_something, need_separator, returnval, found_match)) + { case -1: return -1; case 0: flush = m->reln != '!'; break; default: - if (m->type == FILE_INDIRECT) + if (m->type == FILE_INDIRECT) { + *found_match = 1; *returnval = 1; + } switch (magiccheck(ms, m)) { case -1: @@ -238,7 +272,11 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, goto flush; } - if ((e = handle_annotation(ms, m, firstline)) != 0) { + if (*m->desc) + *found_match = 1; + + if ((e = handle_annotation(ms, m, firstline)) != 0) + { *need_separator = 1; *printed_something = 1; *returnval = 1; @@ -249,16 +287,16 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, * If we are going to print something, we'll need to print * a blank before we print something else. */ - if (*m->desc) { + if (print && *m->desc) { *need_separator = 1; *printed_something = 1; + *returnval = 1; if (print_sep(ms, firstline) == -1) return -1; + if (mprint(ms, m) == -1) + return -1; } - if (print && mprint(ms, m) == -1) - return -1; - switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) { case -1: case 0: @@ -299,10 +337,11 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, continue; } #endif - switch (mget(ms, m, b, bb.fbuf, bb.flen, offset, + switch (mget(ms, m, b, CAST(const unsigned char *, + bb.fbuf), bb.flen, offset, cont_level, mode, text, flip, indir_count, name_count, printed_something, need_separator, - returnval)) { + returnval, found_match)) { case -1: return -1; case 0: @@ -311,8 +350,10 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, flush = 1; break; default: - if (m->type == FILE_INDIRECT) + if (m->type == FILE_INDIRECT) { + *found_match = 1; *returnval = 1; + } flush = 0; break; } @@ -337,6 +378,9 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, } else ms->c.li[cont_level].got_match = 1; + if (*m->desc) + *found_match = 1; + if ((e = handle_annotation(ms, m, firstline)) != 0) { *need_separator = 1; @@ -344,35 +388,36 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, *returnval = 1; return e; } - /* - * If we are going to print something, - * make sure that we have a separator first. - */ - if (*m->desc) { + if (print && *m->desc) { + /* + * This continuation matched. Print + * its message, with a blank before it + * if the previous item printed and + * this item isn't empty. + */ + /* + * If we are going to print something, + * make sure that we have a separator + * first. + */ if (!*printed_something) { *printed_something = 1; if (print_sep(ms, firstline) == -1) return -1; } - } - /* - * This continuation matched. Print - * its message, with a blank before it - * if the previous item printed and - * this item isn't empty. - */ - /* space if previous printed */ - if (*need_separator - && ((m->flag & NOSPACE) == 0) - && *m->desc) { - if (print && - file_printf(ms, " ") == -1) - return -1; + /* space if previous printed */ + if (*need_separator + && (m->flag & NOSPACE) == 0) { + if (file_printf(ms, " ") == -1) + return -1; + } + *returnval = 1; *need_separator = 0; + if (mprint(ms, m) == -1) + return -1; + *need_separator = 1; } - if (print && mprint(ms, m) == -1) - return -1; switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) { @@ -385,9 +430,6 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, break; } - if (*m->desc) - *need_separator = 1; - /* * If we see any continuations * at a higher level, @@ -400,10 +442,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, } if (*printed_something) { firstline = 0; - if (print) - *returnval = 1; } - if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) { + if ((ms->flags & MAGIC_CONTINUE) == 0 && *found_match) { return *returnval; /* don't keep searching */ } cont_level = 0; @@ -460,7 +500,7 @@ varexpand(struct magic_set *ms, char *buf, size_t len, const char *str) size_t l; for (sptr = str; (ptr = strstr(sptr, "${")) != NULL;) { - l = (size_t)(ptr - sptr); + l = CAST(size_t, ptr - sptr); if (l >= len) return -1; memcpy(buf, sptr, l); @@ -526,19 +566,19 @@ mprint(struct magic_set *ms, struct magic *m) switch (m->type) { case FILE_BYTE: - v = file_signextend(ms, m, (uint64_t)p->b); + v = file_signextend(ms, m, CAST(uint64_t, p->b)); switch (check_fmt(ms, desc)) { case -1: return -1; case 1: (void)snprintf(buf, sizeof(buf), "%d", - (unsigned char)v); + CAST(unsigned char, v)); if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) return -1; break; default: if (file_printf(ms, F(ms, desc, "%d"), - (unsigned char) v) == -1) + CAST(unsigned char, v)) == -1) return -1; break; } @@ -548,19 +588,19 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_SHORT: case FILE_BESHORT: case FILE_LESHORT: - v = file_signextend(ms, m, (uint64_t)p->h); + v = file_signextend(ms, m, CAST(uint64_t, p->h)); switch (check_fmt(ms, desc)) { case -1: return -1; case 1: (void)snprintf(buf, sizeof(buf), "%u", - (unsigned short)v); + CAST(unsigned short, v)); if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) return -1; break; default: if (file_printf(ms, F(ms, desc, "%u"), - (unsigned short) v) == -1) + CAST(unsigned short, v)) == -1) return -1; break; } @@ -571,17 +611,19 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BELONG: case FILE_LELONG: case FILE_MELONG: - v = file_signextend(ms, m, (uint64_t)p->l); + v = file_signextend(ms, m, CAST(uint64_t, p->l)); switch (check_fmt(ms, desc)) { case -1: return -1; case 1: - (void)snprintf(buf, sizeof(buf), "%u", (uint32_t) v); + (void)snprintf(buf, sizeof(buf), "%u", + CAST(uint32_t, v)); if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) return -1; break; default: - if (file_printf(ms, F(ms, desc, "%u"), (uint32_t) v) == -1) + if (file_printf(ms, F(ms, desc, "%u"), + CAST(uint32_t, v)) == -1) return -1; break; } @@ -597,13 +639,13 @@ mprint(struct magic_set *ms, struct magic *m) return -1; case 1: (void)snprintf(buf, sizeof(buf), "%" INT64_T_FORMAT "u", - (unsigned long long)v); + CAST(unsigned long long, v)); if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) return -1; break; default: if (file_printf(ms, F(ms, desc, "%" INT64_T_FORMAT "u"), - (unsigned long long) v) == -1) + CAST(unsigned long long, v)) == -1) return -1; break; } @@ -615,9 +657,9 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BESTRING16: case FILE_LESTRING16: if (m->reln == '=' || m->reln == '!') { - if (file_printf(ms, F(ms, desc, "%s"), - file_printable(sbuf, sizeof(sbuf), m->value.s)) - == -1) + if (file_printf(ms, F(ms, desc, "%s"), + file_printable(sbuf, sizeof(sbuf), m->value.s, + sizeof(m->value.s))) == -1) return -1; t = ms->offset + m->vallen; } @@ -632,19 +674,20 @@ mprint(struct magic_set *ms, struct magic *m) if (m->str_flags & STRING_TRIM) { char *last; - while (isspace((unsigned char)*str)) + while (isspace(CAST(unsigned char, *str))) str++; last = str; while (*last) last++; --last; - while (isspace((unsigned char)*last)) + while (isspace(CAST(unsigned char, *last))) last--; *++last = '\0'; } if (file_printf(ms, F(ms, desc, "%s"), - file_printable(sbuf, sizeof(sbuf), str)) == -1) + file_printable(sbuf, sizeof(sbuf), str, + sizeof(p->s) - (str - p->s))) == -1) return -1; if (m->type == FILE_PSTRING) @@ -744,13 +787,14 @@ mprint(struct magic_set *ms, struct magic *m) char *cp; int rval; - cp = strndup((const char *)ms->search.s, ms->search.rm_len); + cp = strndup(RCAST(const char *, ms->search.s), + ms->search.rm_len); if (cp == NULL) { file_oomem(ms, ms->search.rm_len); return -1; } rval = file_printf(ms, F(ms, desc, "%s"), - file_printable(sbuf, sizeof(sbuf), cp)); + file_printable(sbuf, sizeof(sbuf), cp, ms->search.rm_len)); free(cp); if (rval == -1) @@ -776,8 +820,9 @@ mprint(struct magic_set *ms, struct magic *m) t = ms->offset; break; case FILE_DER: - if (file_printf(ms, F(ms, desc, "%s"), - file_printable(sbuf, sizeof(sbuf), ms->ms_value.s)) == -1) + if (file_printf(ms, F(ms, desc, "%s"), + file_printable(sbuf, sizeof(sbuf), ms->ms_value.s, + sizeof(ms->ms_value.s))) == -1) return -1; t = ms->offset; break; @@ -785,7 +830,7 @@ mprint(struct magic_set *ms, struct magic *m) file_magerror(ms, "invalid m->type (%d) in mprint()", m->type); return -1; } - return (int32_t)t; + return CAST(int32_t, t); } private int @@ -832,7 +877,8 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b, p->s[strcspn(p->s, "\r\n")] = '\0'; o = CAST(uint32_t, (ms->offset + strlen(p->s))); if (m->type == FILE_PSTRING) - o += (uint32_t)file_pstring_length_size(m); + o += CAST(uint32_t, + file_pstring_length_size(m)); } break; @@ -898,11 +944,11 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b, case FILE_DER: { o = der_offs(ms, m, nbytes); - if (o == -1 || (size_t)o > nbytes) { + if (o == -1 || CAST(size_t, o) > nbytes) { if ((ms->flags & MAGIC_DEBUG) != 0) { (void)fprintf(stderr, - "Bad DER offset %d nbytes=%zu", - o, nbytes); + "Bad DER offset %d nbytes=%" + SIZE_T_FORMAT "u", o, nbytes); } *op = 0; return 0; @@ -915,10 +961,10 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b, break; } - if ((size_t)o > nbytes) { + if (CAST(size_t, o) > nbytes) { #if 0 - file_error(ms, 0, "Offset out of range %zu > %zu", - (size_t)o, nbytes); + file_error(ms, 0, "Offset out of range %" SIZE_T_FORMAT + "u > %" SIZE_T_FORMAT "u", (size_t)o, nbytes); #endif return -1; } @@ -988,36 +1034,36 @@ cvt_flip(int type, int flip) return type; } } -#define DO_CVT(fld, cast) \ +#define DO_CVT(fld, type) \ if (m->num_mask) \ switch (m->mask_op & FILE_OPS_MASK) { \ case FILE_OPAND: \ - p->fld &= cast m->num_mask; \ + p->fld &= CAST(type, m->num_mask); \ break; \ case FILE_OPOR: \ - p->fld |= cast m->num_mask; \ + p->fld |= CAST(type, m->num_mask); \ break; \ case FILE_OPXOR: \ - p->fld ^= cast m->num_mask; \ + p->fld ^= CAST(type, m->num_mask); \ break; \ case FILE_OPADD: \ - p->fld += cast m->num_mask; \ + p->fld += CAST(type, m->num_mask); \ break; \ case FILE_OPMINUS: \ - p->fld -= cast m->num_mask; \ + p->fld -= CAST(type, m->num_mask); \ break; \ case FILE_OPMULTIPLY: \ - p->fld *= cast m->num_mask; \ + p->fld *= CAST(type, m->num_mask); \ break; \ case FILE_OPDIVIDE: \ - if (cast m->num_mask == 0) \ + if (CAST(type, m->num_mask) == 0) \ return -1; \ - p->fld /= cast m->num_mask; \ + p->fld /= CAST(type, m->num_mask); \ break; \ case FILE_OPMODULO: \ - if (cast m->num_mask == 0) \ + if (CAST(type, m->num_mask) == 0) \ return -1; \ - p->fld %= cast m->num_mask; \ + p->fld %= CAST(type, m->num_mask); \ break; \ } \ if (m->mask_op & FILE_OPINVERSE) \ @@ -1026,61 +1072,61 @@ cvt_flip(int type, int flip) private int cvt_8(union VALUETYPE *p, const struct magic *m) { - DO_CVT(b, (uint8_t)); + DO_CVT(b, uint8_t); return 0; } private int cvt_16(union VALUETYPE *p, const struct magic *m) { - DO_CVT(h, (uint16_t)); + DO_CVT(h, uint16_t); return 0; } private int cvt_32(union VALUETYPE *p, const struct magic *m) { - DO_CVT(l, (uint32_t)); + DO_CVT(l, uint32_t); return 0; } private int cvt_64(union VALUETYPE *p, const struct magic *m) { - DO_CVT(q, (uint64_t)); + DO_CVT(q, uint64_t); return 0; } -#define DO_CVT2(fld, cast) \ +#define DO_CVT2(fld, type) \ if (m->num_mask) \ switch (m->mask_op & FILE_OPS_MASK) { \ case FILE_OPADD: \ - p->fld += cast m->num_mask; \ + p->fld += CAST(type, m->num_mask); \ break; \ case FILE_OPMINUS: \ - p->fld -= cast m->num_mask; \ + p->fld -= CAST(type, m->num_mask); \ break; \ case FILE_OPMULTIPLY: \ - p->fld *= cast m->num_mask; \ + p->fld *= CAST(type, m->num_mask); \ break; \ case FILE_OPDIVIDE: \ - if (cast m->num_mask == 0) \ + if (CAST(type, m->num_mask) == 0) \ return -1; \ - p->fld /= cast m->num_mask; \ + p->fld /= CAST(type, m->num_mask); \ break; \ } \ private int cvt_float(union VALUETYPE *p, const struct magic *m) { - DO_CVT2(f, (float)); + DO_CVT2(f, float); return 0; } private int cvt_double(union VALUETYPE *p, const struct magic *m) { - DO_CVT2(d, (double)); + DO_CVT2(d, double); return 0; } @@ -1136,7 +1182,7 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) * string by p->s, so we need to deduct sz. * Because we can use one of the bytes of the length * after we shifted as NUL termination. - */ + */ len = sz; } while (len--) @@ -1145,14 +1191,14 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) return 1; } case FILE_BESHORT: - p->h = (short)BE16(p); + p->h = CAST(short, BE16(p)); if (cvt_16(p, m) == -1) goto out; return 1; case FILE_BELONG: case FILE_BEDATE: case FILE_BELDATE: - p->l = (int32_t)BE32(p); + p->l = CAST(int32_t, BE32(p)); if (cvt_32(p, m) == -1) goto out; return 1; @@ -1160,19 +1206,19 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) case FILE_BEQDATE: case FILE_BEQLDATE: case FILE_BEQWDATE: - p->q = (uint64_t)BE64(p); + p->q = CAST(uint64_t, BE64(p)); if (cvt_64(p, m) == -1) goto out; return 1; case FILE_LESHORT: - p->h = (short)LE16(p); + p->h = CAST(short, LE16(p)); if (cvt_16(p, m) == -1) goto out; return 1; case FILE_LELONG: case FILE_LEDATE: case FILE_LELDATE: - p->l = (int32_t)LE32(p); + p->l = CAST(int32_t, LE32(p)); if (cvt_32(p, m) == -1) goto out; return 1; @@ -1180,14 +1226,14 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) case FILE_LEQDATE: case FILE_LEQLDATE: case FILE_LEQWDATE: - p->q = (uint64_t)LE64(p); + p->q = CAST(uint64_t, LE64(p)); if (cvt_64(p, m) == -1) goto out; return 1; case FILE_MELONG: case FILE_MEDATE: case FILE_MELDATE: - p->l = (int32_t)ME32(p); + p->l = CAST(int32_t, ME32(p)); if (cvt_32(p, m) == -1) goto out; return 1; @@ -1210,7 +1256,7 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) goto out; return 1; case FILE_BEDOUBLE: - p->q = BE64(p); + p->q = BE64(p); if (cvt_double(p, m) == -1) goto out; return 1; @@ -1301,9 +1347,11 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, || (b = CAST(const char *, memchr(c, '\r', CAST(size_t, (end - c)))))); lines--, b++) { - last = b; if (b < end - 1 && b[0] == '\r' && b[1] == '\n') b++; + if (b < end - 1 && b[0] == '\n') + b++; + last = b; } if (lines) last = end; @@ -1366,7 +1414,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, * might even cause problems */ if (nbytes < sizeof(*p)) - (void)memset(((char *)(void *)p) + nbytes, '\0', + (void)memset(RCAST(char *, RCAST(void *, p)) + nbytes, '\0', sizeof(*p) - nbytes); return 0; } @@ -1407,7 +1455,7 @@ do_ops(struct magic *m, intmax_t lhs, intmax_t off) if (m->in_op & FILE_OPINVERSE) offset = ~offset; - return (uint32_t)offset; + return CAST(uint32_t, offset); } private int @@ -1428,14 +1476,14 @@ msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb, return -1; if (o != 0) { // Not yet! - file_magerror(ms, "non zero offset %zu at" - " level %u", o, cont_level); + file_magerror(ms, "non zero offset %" SIZE_T_FORMAT + "u at level %u", o, cont_level); return -1; } - if ((size_t)-m->offset > b->elen) + if (CAST(size_t, -m->offset) > b->elen) return -1; buffer_init(bb, -1, b->ebuf, b->elen); - ms->eoffset = ms->offset = b->elen + m->offset; + ms->eoffset = ms->offset = CAST(int32_t, b->elen + m->offset); } else { if (cont_level == 0) { normal: @@ -1448,7 +1496,8 @@ msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb, } } if ((ms->flags & MAGIC_DEBUG) != 0) { - fprintf(stderr, "bb=[%p,%zu], %d [b=%p,%zu], [o=%#x, c=%d]\n", + fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u], %d [b=%p,%" + SIZE_T_FORMAT "u], [o=%#x, c=%d]\n", bb->fbuf, bb->flen, ms->offset, b->fbuf, b->flen, m->offset, cont_level); } @@ -1459,7 +1508,8 @@ private int mget(struct magic_set *ms, struct magic *m, const struct buffer *b, const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level, int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count, - int *printed_something, int *need_separator, int *returnval) + int *printed_something, int *need_separator, int *returnval, + int *found_match) { uint32_t offset = ms->offset; struct buffer bb; @@ -1484,8 +1534,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, - if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o), - (uint32_t)nbytes, m) == -1) + if (mcopy(ms, p, m->type, m->flag & INDIR, s, + CAST(uint32_t, offset + o), CAST(uint32_t, nbytes), m) == -1) return -1; if ((ms->flags & MAGIC_DEBUG) != 0) { @@ -1494,7 +1544,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, "u, il=%hu, nc=%hu)\n", m->type, m->flag, offset, o, nbytes, *indir_count, *name_count); - mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); + mdebug(offset, RCAST(char *, RCAST(void *, p)), + sizeof(union VALUETYPE)); #ifndef COMPILE_ONLY file_mdump(m); #endif @@ -1505,40 +1556,58 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, const int sgn = m->in_op & FILE_OPSIGNED; if (m->in_op & FILE_OPINDIRECT) { const union VALUETYPE *q = CAST(const union VALUETYPE *, - ((const void *)(s + offset + off))); - if (OFFSET_OOB(nbytes, offset + off, sizeof(*q))) - return 0; + RCAST(const void *, s + offset + off)); switch (cvt_flip(m->in_type, flip)) { case FILE_BYTE: + if (OFFSET_OOB(nbytes, offset + off, 1)) + return 0; off = SEXT(sgn,8,q->b); break; case FILE_SHORT: + if (OFFSET_OOB(nbytes, offset + off, 2)) + return 0; off = SEXT(sgn,16,q->h); break; case FILE_BESHORT: + if (OFFSET_OOB(nbytes, offset + off, 2)) + return 0; off = SEXT(sgn,16,BE16(q)); break; case FILE_LESHORT: + if (OFFSET_OOB(nbytes, offset + off, 2)) + return 0; off = SEXT(sgn,16,LE16(q)); break; case FILE_LONG: + if (OFFSET_OOB(nbytes, offset + off, 4)) + return 0; off = SEXT(sgn,32,q->l); break; case FILE_BELONG: case FILE_BEID3: + if (OFFSET_OOB(nbytes, offset + off, 4)) + return 0; off = SEXT(sgn,32,BE32(q)); break; case FILE_LEID3: case FILE_LELONG: + if (OFFSET_OOB(nbytes, offset + off, 4)) + return 0; off = SEXT(sgn,32,LE32(q)); break; case FILE_MELONG: + if (OFFSET_OOB(nbytes, offset + off, 4)) + return 0; off = SEXT(sgn,32,ME32(q)); break; case FILE_BEQUAD: + if (OFFSET_OOB(nbytes, offset + off, 8)) + return 0; off = SEXT(sgn,64,BE64(q)); break; case FILE_LEQUAD: + if (OFFSET_OOB(nbytes, offset + off, 8)) + return 0; off = SEXT(sgn,64,LE64(q)); break; default: @@ -1574,7 +1643,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, return 0; lhs = BE32(p); if (in_type == FILE_BEID3) - lhs = cvt_id3(ms, (uint32_t)lhs); + lhs = cvt_id3(ms, CAST(uint32_t, lhs)); offset = do_ops(m, SEXT(sgn,32,lhs), off); break; case FILE_LELONG: @@ -1583,7 +1652,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, return 0; lhs = LE32(p); if (in_type == FILE_LEID3) - lhs = cvt_id3(ms, (uint32_t)lhs); + lhs = cvt_id3(ms, CAST(uint32_t, lhs)); offset = do_ops(m, SEXT(sgn,32,lhs), off); break; case FILE_MELONG: @@ -1626,7 +1695,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, ms->offset = offset; if ((ms->flags & MAGIC_DEBUG) != 0) { - mdebug(offset, (char *)(void *)p, + mdebug(offset, RCAST(char *, RCAST(void *, p)), sizeof(union VALUETYPE)); #ifndef COMPILE_ONLY file_mdump(m); @@ -1714,7 +1783,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, if (rv == 1) { if ((ms->flags & MAGIC_NODESC) == 0 && - file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) { + file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) + { free(rbuf); return -1; } @@ -1744,7 +1814,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, *need_separator = 0; rv = match(ms, ml.magic, ml.nmagic, b, offset + o, mode, text, flip, indir_count, name_count, - printed_something, need_separator, returnval); + printed_something, need_separator, returnval, found_match); + (*name_count)--; if (rv != 1) *need_separator = oneed_separator; return rv; @@ -1775,8 +1846,8 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags) * the ctype functions will work correctly without extra * casting. */ - const unsigned char *a = (const unsigned char *)s1; - const unsigned char *b = (const unsigned char *)s2; + const unsigned char *a = RCAST(const unsigned char *, s1); + const unsigned char *b = RCAST(const unsigned char *, s2); const unsigned char *eb = b + len; uint64_t v; @@ -1971,13 +2042,15 @@ magiccheck(struct magic_set *ms, struct magic *m) case FILE_STRING: case FILE_PSTRING: l = 0; - v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags); + v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen), + m->str_flags); break; case FILE_BESTRING16: case FILE_LESTRING16: l = 0; - v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags); + v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen), + m->str_flags); break; case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */ @@ -2019,7 +2092,7 @@ magiccheck(struct magic_set *ms, struct magic *m) ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0)); if (rc) { file_regerror(&rx, rc, ms); - v = (uint64_t)-1; + v = CAST(uint64_t, -1); } else { regmatch_t pmatch; size_t slen = ms->search.s_len; @@ -2040,15 +2113,15 @@ magiccheck(struct magic_set *ms, struct magic *m) search = CCAST(char *, ""); copy = NULL; } - rc = file_regexec(&rx, (const char *)search, + rc = file_regexec(&rx, RCAST(const char *, search), 1, &pmatch, 0); free(copy); switch (rc) { case 0: - ms->search.s += (int)pmatch.rm_so; - ms->search.offset += (size_t)pmatch.rm_so; - ms->search.rm_len = - (size_t)(pmatch.rm_eo - pmatch.rm_so); + ms->search.s += CAST(int, pmatch.rm_so); + ms->search.offset += CAST(size_t, pmatch.rm_so); + ms->search.rm_len = CAST(size_t, + pmatch.rm_eo - pmatch.rm_so); v = 0; break; @@ -2058,12 +2131,12 @@ magiccheck(struct magic_set *ms, struct magic *m) default: file_regerror(&rx, rc, ms); - v = (uint64_t)-1; + v = CAST(uint64_t, -1); break; } } file_regfree(&rx); - if (v == (uint64_t)-1) + if (v == CAST(uint64_t, -1)) return -1; break; } @@ -2092,7 +2165,7 @@ magiccheck(struct magic_set *ms, struct magic *m) case 'x': if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT - "u == *any* = 1\n", (unsigned long long)v); + "u == *any* = 1\n", CAST(unsigned long long, v)); matched = 1; break; @@ -2100,16 +2173,18 @@ magiccheck(struct magic_set *ms, struct magic *m) matched = v != l; if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %" - INT64_T_FORMAT "u = %d\n", (unsigned long long)v, - (unsigned long long)l, matched); + INT64_T_FORMAT "u = %d\n", + CAST(unsigned long long, v), + CAST(unsigned long long, l), matched); break; case '=': matched = v == l; if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %" - INT64_T_FORMAT "u = %d\n", (unsigned long long)v, - (unsigned long long)l, matched); + INT64_T_FORMAT "u = %d\n", + CAST(unsigned long long, v), + CAST(unsigned long long, l), matched); break; case '>': @@ -2118,15 +2193,16 @@ magiccheck(struct magic_set *ms, struct magic *m) if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "u > %" INT64_T_FORMAT "u = %d\n", - (unsigned long long)v, - (unsigned long long)l, matched); + CAST(unsigned long long, v), + CAST(unsigned long long, l), matched); } else { - matched = (int64_t) v > (int64_t) l; + matched = CAST(int64_t, v) > CAST(int64_t, l); if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "d > %" INT64_T_FORMAT "d = %d\n", - (long long)v, (long long)l, matched); + CAST(long long, v), + CAST(long long, l), matched); } break; @@ -2136,15 +2212,16 @@ magiccheck(struct magic_set *ms, struct magic *m) if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "u < %" INT64_T_FORMAT "u = %d\n", - (unsigned long long)v, - (unsigned long long)l, matched); + CAST(unsigned long long, v), + CAST(unsigned long long, l), matched); } else { - matched = (int64_t) v < (int64_t) l; + matched = CAST(int64_t, v) < CAST(int64_t, l); if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "d < %" INT64_T_FORMAT "d = %d\n", - (long long)v, (long long)l, matched); + CAST(long long, v), + CAST(long long, l), matched); } break; @@ -2153,8 +2230,9 @@ magiccheck(struct magic_set *ms, struct magic *m) if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" INT64_T_FORMAT "x) == %" INT64_T_FORMAT - "x) = %d\n", (unsigned long long)v, - (unsigned long long)l, (unsigned long long)l, + "x) = %d\n", CAST(unsigned long long, v), + CAST(unsigned long long, l), + CAST(unsigned long long, l), matched); break; @@ -2163,9 +2241,9 @@ magiccheck(struct magic_set *ms, struct magic *m) if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" INT64_T_FORMAT "x) != %" INT64_T_FORMAT - "x) = %d\n", (unsigned long long)v, - (unsigned long long)l, (unsigned long long)l, - matched); + "x) = %d\n", CAST(unsigned long long, v), + CAST(unsigned long long, l), + CAST(unsigned long long, l), matched); break; default: @@ -2181,14 +2259,14 @@ private int handle_annotation(struct magic_set *ms, struct magic *m, int firstline) { if ((ms->flags & MAGIC_APPLE) && m->apple[0]) { - if (!firstline && file_printf(ms, "\n- ") == -1) + if (print_sep(ms, firstline) == -1) return -1; if (file_printf(ms, "%.8s", m->apple) == -1) return -1; return 1; } if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) { - if (!firstline && file_printf(ms, "\n- ") == -1) + if (print_sep(ms, firstline) == -1) return -1; if (file_printf(ms, "%s", m->ext) == -1) return -1; @@ -2197,7 +2275,7 @@ handle_annotation(struct magic_set *ms, struct magic *m, int firstline) if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) { char buf[1024]; const char *p; - if (!firstline && file_printf(ms, "\n- ") == -1) + if (print_sep(ms, firstline) == -1) return -1; if (varexpand(ms, buf, sizeof(buf), m->mimetype) == -1) p = m->mimetype; diff --git a/libmagic/src/main/cpp/file/vasprintf.c b/libmagic/src/main/cpp/file/vasprintf.c index ad1d316..c87465b 100644 --- a/libmagic/src/main/cpp/file/vasprintf.c +++ b/libmagic/src/main/cpp/file/vasprintf.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -51,7 +51,7 @@ form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The name of the author may not be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF @@ -108,7 +108,7 @@ you use strange formats. #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: vasprintf.c,v 1.14 2017/08/13 00:21:47 christos Exp $") +FILE_RCSID("@(#)$File: vasprintf.c,v 1.16 2018/10/01 18:45:39 christos Exp $") #endif /* lint */ #include @@ -116,12 +116,8 @@ FILE_RCSID("@(#)$File: vasprintf.c,v 1.14 2017/08/13 00:21:47 christos Exp $") #include #include #include -#ifdef HAVE_LIMITS_H #include -#endif -#ifdef HAVE_STDDEF_H #include -#endif #define ALLOC_CHUNK 2048 #define ALLOC_SECURITY_MARGIN 1024 /* big value because some platforms have very big 'G' exponent */ diff --git a/libmagic/src/test/java/com/hzy/libmagic/ExampleUnitTest.java b/libmagic/src/test/java/com/hzy/libmagic/ExampleUnitTest.java deleted file mode 100644 index 9f85594..0000000 --- a/libmagic/src/test/java/com/hzy/libmagic/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.hzy.libmagic; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file