Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid exporting lib ndk internals #1606

Merged
merged 2 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bugsnag-plugin-android-ndk/src/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,14 @@ target_link_libraries( # Specifies the target library.
# Links the log library to the target library.
log)

# Avoid exporting symbols in release mode to keep internals private
# More symbols are exported in debug mode for the sake of unit testing
set(EXTRA_LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/exported_native_symbols-${CMAKE_BUILD_TYPE}.txt")

set_target_properties(bugsnag-ndk
PROPERTIES
COMPILE_OPTIONS -Werror -Wall -pedantic
LINK_FLAGS "${EXTRA_LINK_FLAGS}"
CXX_STANDARD 17
CXX_STANDARD_REQUIRED YES)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
LIBBUGSNAG_NDK {
global:
bugsnag_*;
Java_*;
bsg_*;
json_*;
BSG_MIGRATOR_CURRENT_VERSION;
migrate_app_v2;
__gxx_*;
__cxa_*;
local:
*;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
LIBBUGSNAG_NDK {
global:
bugsnag_*;
__cxa_*;
__dynamic_cast;
__emutls_get_address;
__gxx_personality_v0;
Java_*;
extern "C++" {
"std::get_terminate()";
"std::set_terminate(void (*)())";
"std::set_unexpected(void (*)())";
"std::get_new_handler()";
"std::set_new_handler(void (*)())";
"std::rethrow_exception(std::exception_ptr)";
"std::__throw_bad_alloc()";
"std::uncaught_exception()";
"std::uncaught_exceptions()";
"std::nothrow";
"std::terminate()";
};

local:
*;
};
47 changes: 0 additions & 47 deletions bugsnag-plugin-android-ndk/src/main/jni/handlers/cpp_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,48 +43,6 @@ void bsg_handler_uninstall_cpp() {
bsg_global_env = NULL;
}

void bsg_write_current_exception_message(char *message, size_t length) {
try {
throw;
} catch (std::exception &exc) {
bsg_strncpy(message, (char *)exc.what(), length);
} catch (std::exception *exc) {
bsg_strncpy(message, (char *)exc->what(), length);
} catch (std::string obj) {
bsg_strncpy(message, (char *)obj.c_str(), length);
} catch (char *obj) {
snprintf(message, length, "%s", obj);
} catch (char obj) {
snprintf(message, length, "%c", obj);
} catch (short obj) {
snprintf(message, length, "%d", obj);
} catch (int obj) {
snprintf(message, length, "%d", obj);
} catch (long obj) {
snprintf(message, length, "%ld", obj);
} catch (long long obj) {
snprintf(message, length, "%lld", obj);
} catch (long double obj) {
snprintf(message, length, "%Lf", obj);
} catch (double obj) {
snprintf(message, length, "%f", obj);
} catch (float obj) {
snprintf(message, length, "%f", obj);
} catch (unsigned char obj) {
snprintf(message, length, "%u", obj);
} catch (unsigned short obj) {
snprintf(message, length, "%u", obj);
} catch (unsigned int obj) {
snprintf(message, length, "%u", obj);
} catch (unsigned long obj) {
snprintf(message, length, "%lu", obj);
} catch (unsigned long long obj) {
snprintf(message, length, "%llu", obj);
} catch (...) {
// no way to describe what this is
}
}

void bsg_handle_cpp_terminate() {
if (bsg_global_env == NULL || bsg_global_env->handling_crash)
return;
Expand All @@ -108,11 +66,6 @@ void bsg_handle_cpp_terminate() {
(char *)tinfo->name(),
sizeof(bsg_global_env->next_event.error.errorClass));
}
size_t message_length = sizeof(bsg_global_env->next_event.error.errorMessage);
char message[message_length];
bsg_write_current_exception_message(message, message_length);
bsg_strncpy(bsg_global_env->next_event.error.errorMessage, (char *)message,
message_length);

if (bsg_run_on_error()) {
bsg_increment_unhandled_count(&bsg_global_env->next_event);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
cmake_minimum_required(VERSION 3.4.1)

add_library(cxx-scenarios-bugsnag SHARED
src/main/cpp/cxx-scenarios-bugsnag.cpp)
src/main/cpp/cxx-scenarios-bugsnag.cpp
src/main/cpp/CXXExceptionSmokeScenario.cpp)

add_library(lib_bugsnag SHARED IMPORTED)
set(BUGSNAG_LIB_DIR
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <jni.h>
#include <stdexcept>

namespace magicstacks {

class FatalProblem : std::runtime_error {
using std::runtime_error::runtime_error;

virtual ~FatalProblem() {}
};

void __attribute__((optnone)) top() {
throw new FatalProblem("well there it is!");
}

void __attribute__((optnone)) middle() { top(); }

void __attribute__((optnone)) start() { middle(); }
} // namespace magicstacks

extern "C" {
JNIEXPORT int JNICALL
Java_com_bugsnag_android_mazerunner_scenarios_CXXExceptionSmokeScenario_crash(
JNIEnv *env, jobject instance) {
magicstacks::start();

return 90;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,6 @@ Java_com_bugsnag_android_mazerunner_scenarios_CXXExceptionOnErrorFalseScenario_c
return 22;
}

JNIEXPORT int JNICALL
Java_com_bugsnag_android_mazerunner_scenarios_CXXExceptionSmokeScenario_crash(
JNIEnv *env,
jobject instance) {
int x = 61;
printf("This one here: %ld\n", (long) f_trigger_an_exception(x > 0));
printf("This one here: %ld\n", (long) f_throw_an_object(x > 0, x));
return 55;
}

JNIEXPORT void JNICALL
Java_com_bugsnag_android_mazerunner_scenarios_CXXStartScenario_activate(
JNIEnv *env,
Expand Down
13 changes: 6 additions & 7 deletions features/smoke_tests/unhandled.feature
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ Scenario: C++ exception thrown with overwritten config

# Exception details
And the error payload field "events" is an array with 1 elements
And the exception "message" equals "How about NO"
And the exception "errorClass" demangles to "magicstacks::FatalProblem*"
And the exception "type" equals "c"
And the event "unhandled" is true
And the event "severity" equals "error"
Expand All @@ -202,12 +202,11 @@ Scenario: C++ exception thrown with overwritten config
# Stacktrace validation
And the error payload field "events.0.exceptions.0.stacktrace" is a non-empty array
And the event stacktrace identifies the program counter
And the event "exceptions.0.stacktrace.0.method" is not null
And the event "exceptions.0.stacktrace.0.file" is not null
And the error payload field "events.0.exceptions.0.stacktrace.0.frameAddress" is greater than 0
And the error payload field "events.0.exceptions.0.stacktrace.0.symbolAddress" is greater than 0
And the error payload field "events.0.exceptions.0.stacktrace.0.loadAddress" is greater than 0
And the error payload field "events.0.exceptions.0.stacktrace.0.lineNumber" is greater than 0
And the first significant stack frame methods and files should match:
| magicstacks::top() | | libcxx-scenarios-bugsnag.so |
| magicstacks::middle() | | libcxx-scenarios-bugsnag.so |
| magicstacks::start() | | libcxx-scenarios-bugsnag.so |
| Java_com_bugsnag_android_mazerunner_scenarios_CXXExceptionSmokeScenario_crash | | libcxx-scenarios-bugsnag.so |

# App data
And the event binary arch field is valid
Expand Down
10 changes: 9 additions & 1 deletion features/steps/android_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@
Maze.check.include(possible_values.raw.flatten, value)
end

Then("the exception {string} demangles to {string}") do |keypath, expected_value|
actual_value = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.exceptions.0.#{keypath}")
demangled_value = `c++filt --types --no-strip-underscore '#{actual_value}'`.chomp
Maze.check.true(demangled_value == expected_value,
"expected '#{demangled_value}' to equal '#{expected_value}'")
end

# Checks whether the first significant frames match several given frames
#
# @param expected_values [Array] A table dictating the expected files and methods of the frames
Expand All @@ -110,7 +117,8 @@
method = frame["method"] if method == "_#{frame["method"]}"
insignificant = method.start_with?("bsg_") ||
method.start_with?("std::") ||
method.start_with?("__cxx") ||
method.start_with?("__cx") ||
method.start_with?("0x") ||
frame["file"].start_with?("/system/") ||
frame["file"].end_with?("libbugsnag-ndk.so")
{ :index => index, :method => method, :file => frame["file"] } unless insignificant
Expand Down