aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp38
-rw-r--r--ChangeLog9
-rw-r--r--METADATA1
-rw-r--r--Makefile8
-rw-r--r--add-test/add_test.c4
-rw-r--r--fuzzer/Android.bp58
-rw-r--r--fuzzer/README.md78
-rw-r--r--fuzzer/gsm_dec_fuzzer.cpp98
-rw-r--r--fuzzer/gsm_enc_fuzzer.cpp96
-rw-r--r--inc/config.h2
-rw-r--r--inc/gsm.h10
-rw-r--r--inc/private.h8
-rw-r--r--inc/toast.h4
13 files changed, 408 insertions, 6 deletions
diff --git a/Android.bp b/Android.bp
index 8fb5ad9..a1468dd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,9 +14,41 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["external_libgsm_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "external_libgsm_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-0BSD",
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ ],
+ license_text: [
+ "COPYRIGHT",
+ ],
+}
+
cc_library_static {
name: "libgsm",
vendor_available: true,
+ host_supported: true,
srcs: [
"src/add.c",
@@ -43,6 +75,12 @@ cc_library_static {
"-Wno-unused-parameter",
],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+
export_include_dirs: ["inc"],
min_sdk_version: "apex_inherit",
}
diff --git a/ChangeLog b/ChangeLog
index d21eae9..530a416 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Mar 27 15:18:06 2020
+
+ * Release 1.0 Patchlevel 19
+ Make it easier to include gsm.h from C++ by wrapping it with macros.
+ Throw a #define _POSIX_C_SOURCE 200809L into toast.h to make it
+ possible for Linux glibc to just work.
+ (Thanks to enh@google.com for the suggestion; errors are mine.)
+ Switch from compress/.Z to gzip/.gz
+
Sat May 5 21:48:20 2018
* Release 1.0 Patchlevel 18
diff --git a/METADATA b/METADATA
index c85cc99..5a319b1 100644
--- a/METADATA
+++ b/METADATA
@@ -10,6 +10,7 @@ third_party {
value: "http://www.quut.com/gsm/gsm-1.0.18.tar.gz"
}
version: "1.0.18"
+ license_type: NOTICE
last_upgrade_date {
year: 2018
month: 12
diff --git a/Makefile b/Makefile
index d5c0c90..eaf94d5 100644
--- a/Makefile
+++ b/Makefile
@@ -102,7 +102,7 @@ AR = ar
ARFLAGS = cr
RMFLAGS =
FIND = find
-COMPRESS = compress
+COMPRESS = gzip
COMPRESSFLAGS =
# RANLIB = true
RANLIB = ranlib
@@ -401,14 +401,14 @@ $(GSM_INSTALL_LIB)/libgsm.a: $(LIBGSM)
# Distribution
-dist: gsm-1.0.tar.Z
+dist: gsm-1.0.tar.gz
@echo dist: Done.
-gsm-1.0.tar.Z: $(STUFF) $(SOURCES) $(HEADERS) $(MANUALS)
+gsm-1.0.tar.gz: $(STUFF) $(SOURCES) $(HEADERS) $(MANUALS)
( cd $(ROOT)/..; \
tar cvf - `cat $(ROOT)/gsm-1.0/MANIFEST \
| sed '/^#/d'` \
- ) | $(COMPRESS) $(COMPRESSFLAGS) > $(ROOT)/gsm-1.0.tar.Z
+ ) | $(COMPRESS) $(COMPRESSFLAGS) > $(ROOT)/gsm-1.0.tar.gz
# Clean
diff --git a/add-test/add_test.c b/add-test/add_test.c
index 6b23e9d..bf0e4b1 100644
--- a/add-test/add_test.c
+++ b/add-test/add_test.c
@@ -6,6 +6,10 @@
/* $Header: /tmp_amd/presto/export/kbs/jutta/src/gsm/RCS/add_test.c,v 1.2 1994/05/10 20:18:17 jutta Exp $ */
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
new file mode 100644
index 0000000..3dc0524
--- /dev/null
+++ b/fuzzer/Android.bp
@@ -0,0 +1,58 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "external_libgsm_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["external_libgsm_license"],
+}
+
+cc_defaults {
+ name: "gsm_fuzzer_defaults",
+ host_supported: true,
+ static_libs: [
+ "libgsm",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_fuzz {
+ name: "gsm_dec_fuzzer",
+ defaults: ["gsm_fuzzer_defaults"],
+ srcs: [
+ "gsm_dec_fuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "gsm_enc_fuzzer",
+ defaults: ["gsm_fuzzer_defaults"],
+ srcs: [
+ "gsm_enc_fuzzer.cpp",
+ ],
+}
diff --git a/fuzzer/README.md b/fuzzer/README.md
new file mode 100644
index 0000000..2c3f35f
--- /dev/null
+++ b/fuzzer/README.md
@@ -0,0 +1,78 @@
+# Fuzzer for libgsm codec
+
+## Plugin Design Considerations
+The fuzzer plugin for GSM is designed based on the understanding of the
+codec and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+GSM supports the following options:
+1. Verbosity (parameter name: `GSM_VERBOSE`)
+2. Fastness (parameter name: `GSM_OPT_FAST`)
+3. WAV49 Format (parameter name: `GSM_OPT_WAV49`)
+4. LTP Cut speed-up (encoder only) (parameter name: `GSM_OPT_LTP_CUT`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `GSM_VERBOSE` | 0. `Verbosity disabled` 1. `Verbosity enabled` | Bit 0 (LSB) of 1st byte of data. |
+| `GSM_OPT_FAST` | 0. `Regular algorithm will be used` 1. `Faster version of the algorithm will be used` | Bit 1 (LSB) of 1st byte of data. |
+| `GSM_OPT_LTP_CUT` | 0. `Disable LTP cut-off optimization` 1. `Enable LTP cut-off optimization` | Bit 2 (LSB) of 1st byte of data. |
+| `GSM_OPT_WAV49` | 0. `Disable WAV49 output in the encoder.` 1. `Enable WAV49 format in the encoder.` | Bit 3 (LSB) of 1st byte of data. |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the codec using a loop.
+###### For the Decoder:
+ * If the size of media file is less than 65 bytes, (65 - size) bytes are padded and then sent to
+ the decoder so that decode happens for all the input files, regardless of their size.
+ GSM decoder consumes alternating frames of 33 and 32 bytes, so 65 bytes of input are needed.
+ * If the decode operation was successful, the input is advanced by the frame size
+ * If the decode operation was un-successful, the input is still advanced by frame size so
+that the fuzzer can proceed to feed the next frame.
+###### For the Encoder:
+ * If the size of media file is less than 320 bytes(160 signed 16-bit words), bytes are padded and then sent to
+ the encoder so that encode happens for all the input files, regardless of their size.
+ GSM encoder consumes 160 signed 16-bit words, so 320 bytes of input are needed.
+ * If the encode operation was successful, the input is advanced by the frame size
+ * If the encode operation was un-successful, the input is still advanced by frame size so
+that the fuzzer can proceed to feed the next frame.
+
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build gsm_dec_fuzzer and gsm_enc_fuzzer binaries.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) gsm_dec_fuzzer
+ $ mm -j$(nproc) gsm_enc_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some gsm files (decoder)/raw files (encoder) to that folder
+Push this directory to device.
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/gsm_dec_fuzzer/gsm_dec_fuzzer CORPUS_DIR
+ $ adb shell /data/fuzz/arm64/gsm_enc_fuzzer/gsm_enc_fuzzer CORPUS_DIR
+```
+To run on host
+```
+ $ $ANDROID_HOST_OUT/fuzz/x86_64/gsm_dec_fuzzer/gsm_dec_fuzzer CORPUS_DIR
+ $ $ANDROID_HOST_OUT/fuzz/x86_64/gsm_enc_fuzzer/gsm_enc_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/fuzzer/gsm_dec_fuzzer.cpp b/fuzzer/gsm_dec_fuzzer.cpp
new file mode 100644
index 0000000..f981eb7
--- /dev/null
+++ b/fuzzer/gsm_dec_fuzzer.cpp
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <stdint.h>
+#include <string.h>
+#include "gsm.h"
+
+constexpr int16_t kGsmInFrameSize = 33;
+constexpr int16_t kGsmInFrameSizeMinus1 = kGsmInFrameSize - 1;
+constexpr int16_t kGsmOutFrameSize = 160;
+constexpr int16_t kGsmTotalInFrameSize = (kGsmInFrameSize + kGsmInFrameSizeMinus1);
+constexpr int16_t kGsmTotalOutFrameSize = (kGsmOutFrameSize * 2);
+
+class Codec {
+ public:
+ Codec() = default;
+ ~Codec() { deInitDecoder(); }
+ bool initDecoder();
+ void decodeFrames(const uint8_t *data, size_t size);
+ void deInitDecoder();
+
+ private:
+ gsm mGsm = nullptr;
+};
+
+bool Codec::initDecoder() {
+ mGsm = gsm_create();
+ if (mGsm) {
+ int msopt = 1;
+ gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Codec::decodeFrames(const uint8_t *data, size_t size) {
+ uint8_t firstByte = *data;
+ int32_t verbosity = firstByte & 0x01;
+ int32_t fast = (firstByte >> 1) & 0x01;
+ gsm_option(mGsm, GSM_OPT_VERBOSE, &verbosity);
+ gsm_option(mGsm, GSM_OPT_FAST, &fast);
+ gsm_byte *readPointer = const_cast<uint8_t *>(data);
+ uint8_t tmpData[kGsmTotalInFrameSize];
+ gsm_signal out[kGsmTotalOutFrameSize];
+
+ while (size > 0) {
+ if (size < kGsmTotalInFrameSize) {
+ memset(tmpData, 0, sizeof(tmpData));
+ memcpy(tmpData, data, size);
+ size = kGsmTotalInFrameSize;
+ readPointer = tmpData;
+ }
+ gsm_decode(mGsm, readPointer, out);
+ readPointer += kGsmInFrameSize;
+ size -= kGsmInFrameSize;
+
+ gsm_decode(mGsm, readPointer, out);
+ readPointer += kGsmInFrameSizeMinus1;
+ size -= kGsmInFrameSizeMinus1;
+ }
+}
+
+void Codec::deInitDecoder() {
+ gsm_destroy(mGsm);
+ mGsm = nullptr;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ Codec *codec = new Codec();
+ if (!codec) {
+ return 0;
+ }
+ if (codec->initDecoder()) {
+ codec->decodeFrames(data, size);
+ }
+ delete codec;
+ return 0;
+}
diff --git a/fuzzer/gsm_enc_fuzzer.cpp b/fuzzer/gsm_enc_fuzzer.cpp
new file mode 100644
index 0000000..3e00f85
--- /dev/null
+++ b/fuzzer/gsm_enc_fuzzer.cpp
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <stdint.h>
+#include <string.h>
+#include <algorithm>
+
+#include "gsm.h"
+
+constexpr size_t kGsmInNumSamples = 160;
+constexpr size_t kGsmInBufferSize = kGsmInNumSamples * sizeof(gsm_signal);
+
+enum { IDX_VERBOSITY, IDX_FAST, IDX_LTP_CUT, IDX_WAV49, IDX_LAST };
+
+class Codec {
+ public:
+ Codec() = default;
+ ~Codec() { deInitEncoder(); }
+ bool initEncoder();
+ void encodeFrames(uint8_t *data, size_t size);
+ void deInitEncoder();
+
+ private:
+ gsm mGsm = nullptr;
+};
+
+bool Codec::initEncoder() {
+ mGsm = gsm_create();
+ return mGsm ? true : false;
+}
+
+void Codec::encodeFrames(uint8_t *data, size_t size) {
+ int32_t verbosity = data[IDX_VERBOSITY] & 0x01;
+ int32_t fast = data[IDX_FAST] & 0x01;
+ int32_t ltp_cut = data[IDX_LTP_CUT] & 0x01;
+ int32_t wav49 = data[IDX_WAV49] & 0x01;
+ gsm_option(mGsm, GSM_OPT_VERBOSE, &verbosity);
+ gsm_option(mGsm, GSM_OPT_FAST, &fast);
+ gsm_option(mGsm, GSM_OPT_LTP_CUT, &ltp_cut);
+ gsm_option(mGsm, GSM_OPT_WAV49, &wav49);
+ data += IDX_LAST;
+ size -= IDX_LAST;
+
+ while (size > 0) {
+ gsm_signal tmpData[kGsmInNumSamples];
+ gsm_frame out;
+ size_t frameSize = std::min(size, kGsmInBufferSize);
+
+ memcpy(tmpData, data, frameSize);
+ if (frameSize < kGsmInBufferSize) {
+ memset(reinterpret_cast<uint8_t *>(tmpData) + frameSize, data[0],
+ kGsmInBufferSize - frameSize);
+ }
+ gsm_encode(mGsm, tmpData, out);
+ data += frameSize;
+ size -= frameSize;
+ }
+}
+
+void Codec::deInitEncoder() {
+ if (mGsm) {
+ gsm_destroy(mGsm);
+ mGsm = nullptr;
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < IDX_LAST) {
+ return 0;
+ }
+ Codec *codec = new Codec();
+ if (!codec) {
+ return 0;
+ }
+ if (codec->initEncoder()) {
+ codec->encodeFrames(const_cast<uint8_t *>(data), size);
+ }
+ delete codec;
+ return 0;
+}
diff --git a/inc/config.h b/inc/config.h
index 223c9d4..dfb1ead 100644
--- a/inc/config.h
+++ b/inc/config.h
@@ -25,7 +25,7 @@
/*efine HAS__FSETMODE 1 /* _fsetmode -- set file mode */
#define HAS_STRING_H 1 /* /usr/include/string.h */
-#define HAS_STRINGS_H 1 /* /usr/include/strings.h */
+/*efine HAS_STRINGS_H 1 /* /usr/include/strings.h */
#define HAS_UNISTD_H 1 /* /usr/include/unistd.h */
#define HAS_UTIME 1 /* POSIX utime(path, times) */
diff --git a/inc/gsm.h b/inc/gsm.h
index 5b3c3eb..55c02c4 100644
--- a/inc/gsm.h
+++ b/inc/gsm.h
@@ -10,6 +10,10 @@
#define GSM_H
#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
# define NeedFunctionPrototypes 1
#endif
@@ -43,7 +47,7 @@ typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */
#define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */
-#define GSM_PATCHLEVEL 18
+#define GSM_PATCHLEVEL 19
#define GSM_MINOR 0
#define GSM_MAJOR 1
@@ -68,4 +72,8 @@ extern void gsm_implode GSM_P((gsm, gsm_signal *, gsm_byte *));
#undef GSM_P
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* GSM_H */
diff --git a/inc/private.h b/inc/private.h
index d1b1510..d9bed03 100644
--- a/inc/private.h
+++ b/inc/private.h
@@ -9,6 +9,10 @@
#ifndef PRIVATE_H
#define PRIVATE_H
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
typedef short word; /* 16 bit signed int */
typedef long longword; /* 32 bit signed int */
@@ -266,4 +270,8 @@ extern word gsm_FAC[8];
#include "unproto.h"
+#ifdef __cplusplus
+ } // extern "C"
+#endif
+
#endif /* PRIVATE_H */
diff --git a/inc/toast.h b/inc/toast.h
index b42d9ae..847e8d4 100644
--- a/inc/toast.h
+++ b/inc/toast.h
@@ -11,6 +11,10 @@
#include "config.h"
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
#include <sys/types.h>
#include <sys/stat.h>