From a2483a839264369482fff135d33f007ded266d3c Mon Sep 17 00:00:00 2001
From: Bent Bisballe Nyeng <deva@aasimon.org>
Date: Wed, 4 Aug 2021 11:37:39 +0200
Subject: Fix crash when loading a kit with more channels than the engine was
 compiled for.

---
 src/drumgizmo.cc      | 12 ++++++++++++
 src/events_ds.h       |  6 ++++++
 src/inputprocessor.cc | 25 +++++++++++++++++++++++++
 3 files changed, 43 insertions(+)

(limited to 'src')

diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index d3665c2..abe57be 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -197,6 +197,11 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
 
 		for(size_t c = 0; c < kit.channels.size(); ++c)
 		{
+			if(c >= NUM_CHANNELS) // kit may have more channels than the engine
+			{
+				break;
+			}
+
 			sample_t *buf = samples;
 			bool internal = false;
 			if(oe.getBuffer(c))
@@ -224,6 +229,11 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
 		size_t kitpos = pos * ratio;
 		for(size_t c = 0; c < kit.channels.size(); ++c)
 		{
+			if(c >= NUM_CHANNELS) // kit may have more channels than the engine
+			{
+				break;
+			}
+
 			sample_t *buf = samples;
 			bool internal = false;
 			if(oe.getBuffer(c))
@@ -339,6 +349,8 @@ repeat:
 
 void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz)
 {
+	assert(ch < NUM_CHANNELS);
+
 	// Store local values of settings to ensure they don't change intra-iteration
 	const auto enable_bleed_control = settings.enable_bleed_control.load();
 	const auto master_bleed = settings.master_bleed.load();
diff --git a/src/events_ds.h b/src/events_ds.h
index fdab881..41287d1 100644
--- a/src/events_ds.h
+++ b/src/events_ds.h
@@ -149,6 +149,8 @@ private:
 template <typename T, typename... Args>
 T& EventsDS::emplace(channel_t ch, Args&&... args)
 {
+	assert(ch < NUM_CHANNELS);
+
 	// add new event types here
 	static_assert(std::is_same<T, SampleEvent>::value, "Check event type");
 
@@ -180,6 +182,8 @@ T& EventsDS::get(EventID event_id)
 template <typename T>
 ContainerRange<std::vector<T>> EventsDS::iterateOver(channel_t ch)
 {
+	assert(ch < NUM_CHANNELS);
+
 	// add new event types here
 	static_assert(std::is_same<T, SampleEvent>::value, "Check event type");
 
@@ -193,6 +197,8 @@ ContainerRange<std::vector<T>> EventsDS::iterateOver(channel_t ch)
 template <typename T>
 T& EventsDS::getSample(EventInfo const& info)
 {
+	assert(info.ch < NUM_CHANNELS);
+
 	// add new event types here
 	static_assert(std::is_same<T, SampleEvent>::value, "Check event type");
 
diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc
index abd2898..822e8b1 100644
--- a/src/inputprocessor.cc
+++ b/src/inputprocessor.cc
@@ -163,6 +163,11 @@ static void applyChokeGroup(Settings& settings, DrumKit& kit,
 	// Add event to ramp down all existing events with the same groupname.
 	for(const auto& ch : kit.channels)
 	{
+		if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine
+		{
+			continue;
+		}
+
 		for(auto& event_sample : events_ds.iterateOver<SampleEvent>(ch.num))
 		{
 			if(event_sample.group == instr.getGroup() &&
@@ -186,6 +191,11 @@ static void applyDirectedChoke(Settings& settings, DrumKit& kit,
 		// Add event to ramp down all existing events with the same groupname.
 		for(const auto& ch : kit.channels)
 		{
+			if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine
+			{
+				continue;
+			}
+
 			for(auto& event_sample : events_ds.iterateOver<SampleEvent>(ch.num))
 			{
 				if(choke.instrument_id == event_sample.instrument_id &&
@@ -264,6 +274,11 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos,
 	bool new_group_added = false;
 	for(Channel& ch: kit.channels)
 	{
+		if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine
+		{
+			continue;
+		}
+
 		const auto af = sample->getAudioFile(ch);
 		if(af == nullptr || !af->isValid())
 		{
@@ -330,6 +345,11 @@ bool InputProcessor::processChoke(event_t& event,
 	// Add event to ramp down all existing events with the same groupname.
 	for(const auto& ch : kit.channels)
 	{
+		if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine
+		{
+			continue;
+		}
+
 		for(auto& event_sample : events_ds.iterateOver<SampleEvent>(ch.num))
 		{
 			if(event_sample.instrument_id == instrument_id &&
@@ -357,6 +377,11 @@ bool InputProcessor::processStop(event_t& event)
 		int num_active_events = 0;
 		for(auto& ch: kit.channels)
 		{
+			if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine
+			{
+				continue;
+			}
+
 			num_active_events += events_ds.numberOfEvents(ch.num);
 		}
 
-- 
cgit v1.2.3