Fix reading from freed memory in rpl::take().
This commit is contained in:
		
							parent
							
								
									583b0fa778
								
							
						
					
					
						commit
						6445c0563e
					
				
					 5 changed files with 30 additions and 8 deletions
				
			
		| 
						 | 
					@ -329,6 +329,11 @@ public:
 | 
				
			||||||
	Type *make_state(Args&& ...args) const;
 | 
						Type *make_state(Args&& ...args) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void terminate() const;
 | 
						void terminate() const;
 | 
				
			||||||
 | 
						auto terminator() const {
 | 
				
			||||||
 | 
							return [self = *this] {
 | 
				
			||||||
 | 
								self.terminate();
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const details::type_erased_handlers<Value, Error> *comparable() const {
 | 
						const details::type_erased_handlers<Value, Error> *comparable() const {
 | 
				
			||||||
		return _handlers.get();
 | 
							return _handlers.get();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ public:
 | 
				
			||||||
			[consumer, state](producer<Value, Error> &&inner) {
 | 
								[consumer, state](producer<Value, Error> &&inner) {
 | 
				
			||||||
				state->finished = false;
 | 
									state->finished = false;
 | 
				
			||||||
				state->alive = lifetime();
 | 
									state->alive = lifetime();
 | 
				
			||||||
				auto started = std::move(inner).start(
 | 
									std::move(inner).start(
 | 
				
			||||||
				[consumer](auto &&value) {
 | 
									[consumer](auto &&value) {
 | 
				
			||||||
					consumer.put_next_forward(std::forward<decltype(value)>(value));
 | 
										consumer.put_next_forward(std::forward<decltype(value)>(value));
 | 
				
			||||||
				}, [consumer](auto &&error) {
 | 
									}, [consumer](auto &&error) {
 | 
				
			||||||
| 
						 | 
					@ -55,10 +55,7 @@ public:
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						state->finished = true;
 | 
											state->finished = true;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				});
 | 
									}, state->alive);
 | 
				
			||||||
				if (started) {
 | 
					 | 
				
			||||||
					state->alive = std::move(started);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}, [consumer](auto &&error) {
 | 
								}, [consumer](auto &&error) {
 | 
				
			||||||
				consumer.put_error_forward(std::forward<decltype(error)>(error));
 | 
									consumer.put_error_forward(std::forward<decltype(error)>(error));
 | 
				
			||||||
			}, [consumer, state] {
 | 
								}, [consumer, state] {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -406,6 +406,24 @@ TEST_CASE("basic operators tests", "[rpl::operators]") {
 | 
				
			||||||
					*sum += "done";
 | 
										*sum += "done";
 | 
				
			||||||
				}, lifetime);
 | 
									}, lifetime);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		REQUIRE(*sum == "012done");
 | 
							{
 | 
				
			||||||
 | 
								rpl::lifetime lifetime;
 | 
				
			||||||
 | 
								rpl::ints(3) | take(3)
 | 
				
			||||||
 | 
									| start_with_next_done([=](int value) {
 | 
				
			||||||
 | 
										*sum += std::to_string(value);
 | 
				
			||||||
 | 
									}, [=] {
 | 
				
			||||||
 | 
										*sum += "done";
 | 
				
			||||||
 | 
									}, lifetime);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								rpl::lifetime lifetime;
 | 
				
			||||||
 | 
								rpl::ints(3) | take(10)
 | 
				
			||||||
 | 
									| start_with_next_done([=](int value) {
 | 
				
			||||||
 | 
										*sum += std::to_string(value);
 | 
				
			||||||
 | 
									}, [=] {
 | 
				
			||||||
 | 
										*sum += "done";
 | 
				
			||||||
 | 
									}, lifetime);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							REQUIRE(*sum == "012done012done012done");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -346,7 +346,7 @@ template <typename Handlers>
 | 
				
			||||||
inline void producer_base<Value, Error, Generator>::start_existing(
 | 
					inline void producer_base<Value, Error, Generator>::start_existing(
 | 
				
			||||||
		const consumer_type<Handlers> &consumer,
 | 
							const consumer_type<Handlers> &consumer,
 | 
				
			||||||
		lifetime &alive_while) && {
 | 
							lifetime &alive_while) && {
 | 
				
			||||||
	alive_while.add([consumer] { consumer.terminate(); });
 | 
						alive_while.add(consumer.terminator());
 | 
				
			||||||
	consumer.add_lifetime(std::move(_generator)(consumer));
 | 
						consumer.add_lifetime(std::move(_generator)(consumer));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ public:
 | 
				
			||||||
			limit = _count
 | 
								limit = _count
 | 
				
			||||||
		](const auto &consumer) mutable {
 | 
							](const auto &consumer) mutable {
 | 
				
			||||||
			auto count = consumer.template make_state<int>(limit);
 | 
								auto count = consumer.template make_state<int>(limit);
 | 
				
			||||||
			return std::move(initial).start(
 | 
								auto initial_consumer = make_consumer<Value, Error>(
 | 
				
			||||||
			[consumer, count](auto &&value) {
 | 
								[consumer, count](auto &&value) {
 | 
				
			||||||
				auto left = (*count)--;
 | 
									auto left = (*count)--;
 | 
				
			||||||
				if (left) {
 | 
									if (left) {
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,8 @@ public:
 | 
				
			||||||
			}, [consumer] {
 | 
								}, [consumer] {
 | 
				
			||||||
				consumer.put_done();
 | 
									consumer.put_done();
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
								consumer.add_lifetime(initial_consumer.terminator());
 | 
				
			||||||
 | 
								return std::move(initial).start_existing(initial_consumer);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue