Skip to content

Commit dbfa13d

Browse files
committed
Fixed unsoundness in .and_then()/.then() service combinators
1 parent e7c2439 commit dbfa13d

File tree

8 files changed

+164
-116
lines changed

8 files changed

+164
-116
lines changed

actix-service/CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changes
22

3+
## [1.0.5] - 2020-01-16
4+
5+
### Fixed
6+
7+
* Fixed unsoundness in .and_then()/.then() service combinators
8+
39
## [1.0.4] - 2020-01-15
410

511
### Fixed

actix-service/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "actix-service"
3-
version = "1.0.4"
3+
version = "1.0.5"
44
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
55
description = "Actix service"
66
keywords = ["network", "framework", "async", "futures"]

actix-service/src/and_then.rs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::future::Future;
22
use std::pin::Pin;
3+
use std::rc::Rc;
34
use std::task::{Context, Poll};
45

56
use super::{Service, ServiceFactory};
@@ -9,7 +10,7 @@ use crate::cell::Cell;
910
/// of another service which completes successfully.
1011
///
1112
/// This is created by the `ServiceExt::and_then` method.
12-
pub struct AndThenService<A, B>(Cell<A>, Cell<B>);
13+
pub(crate) struct AndThenService<A, B>(Cell<(A, B)>);
1314

1415
impl<A, B> AndThenService<A, B> {
1516
/// Create new `AndThen` combinator
@@ -18,13 +19,13 @@ impl<A, B> AndThenService<A, B> {
1819
A: Service,
1920
B: Service<Request = A::Response, Error = A::Error>,
2021
{
21-
Self(Cell::new(a), Cell::new(b))
22+
Self(Cell::new((a, b)))
2223
}
2324
}
2425

2526
impl<A, B> Clone for AndThenService<A, B> {
2627
fn clone(&self) -> Self {
27-
AndThenService(self.0.clone(), self.1.clone())
28+
AndThenService(self.0.clone())
2829
}
2930
}
3031

@@ -39,8 +40,9 @@ where
3940
type Future = AndThenServiceResponse<A, B>;
4041

4142
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
42-
let not_ready = { !self.0.get_mut().poll_ready(cx)?.is_ready() };
43-
if !self.1.poll_ready(cx)?.is_ready() || not_ready {
43+
let srv = self.0.get_mut();
44+
let not_ready = !srv.0.poll_ready(cx)?.is_ready();
45+
if !srv.1.poll_ready(cx)?.is_ready() || not_ready {
4446
Poll::Pending
4547
} else {
4648
Poll::Ready(Ok(()))
@@ -49,13 +51,13 @@ where
4951

5052
fn call(&mut self, req: A::Request) -> Self::Future {
5153
AndThenServiceResponse {
52-
state: State::A(self.0.get_mut().call(req), Some(self.1.clone())),
54+
state: State::A(self.0.get_mut().0.call(req), Some(self.0.clone())),
5355
}
5456
}
5557
}
5658

5759
#[pin_project::pin_project]
58-
pub struct AndThenServiceResponse<A, B>
60+
pub(crate) struct AndThenServiceResponse<A, B>
5961
where
6062
A: Service,
6163
B: Service<Request = A::Response, Error = A::Error>,
@@ -70,7 +72,7 @@ where
7072
A: Service,
7173
B: Service<Request = A::Response, Error = A::Error>,
7274
{
73-
A(#[pin] A::Future, Option<Cell<B>>),
75+
A(#[pin] A::Future, Option<Cell<(A, B)>>),
7476
B(#[pin] B::Future),
7577
Empty,
7678
}
@@ -92,7 +94,7 @@ where
9294
Poll::Ready(res) => {
9395
let mut b = b.take().unwrap();
9496
this.state.set(State::Empty); // drop fut A
95-
let fut = b.get_mut().call(res);
97+
let fut = b.get_mut().1.call(res);
9698
this.state.set(State::B(fut));
9799
self.poll(cx)
98100
}
@@ -108,7 +110,7 @@ where
108110
}
109111

110112
/// `.and_then()` service factory combinator
111-
pub struct AndThenServiceFactory<A, B>
113+
pub(crate) struct AndThenServiceFactory<A, B>
112114
where
113115
A: ServiceFactory,
114116
A::Config: Clone,
@@ -119,8 +121,7 @@ where
119121
InitError = A::InitError,
120122
>,
121123
{
122-
a: A,
123-
b: B,
124+
inner: Rc<(A, B)>,
124125
}
125126

126127
impl<A, B> AndThenServiceFactory<A, B>
@@ -136,7 +137,9 @@ where
136137
{
137138
/// Create new `AndThenFactory` combinator
138139
pub(crate) fn new(a: A, b: B) -> Self {
139-
Self { a, b }
140+
Self {
141+
inner: Rc::new((a, b)),
142+
}
140143
}
141144
}
142145

@@ -161,34 +164,34 @@ where
161164
type Future = AndThenServiceFactoryResponse<A, B>;
162165

163166
fn new_service(&self, cfg: A::Config) -> Self::Future {
167+
let inner = &*self.inner;
164168
AndThenServiceFactoryResponse::new(
165-
self.a.new_service(cfg.clone()),
166-
self.b.new_service(cfg),
169+
inner.0.new_service(cfg.clone()),
170+
inner.1.new_service(cfg),
167171
)
168172
}
169173
}
170174

171175
impl<A, B> Clone for AndThenServiceFactory<A, B>
172176
where
173-
A: ServiceFactory + Clone,
177+
A: ServiceFactory,
174178
A::Config: Clone,
175179
B: ServiceFactory<
176-
Config = A::Config,
177-
Request = A::Response,
178-
Error = A::Error,
179-
InitError = A::InitError,
180-
> + Clone,
180+
Config = A::Config,
181+
Request = A::Response,
182+
Error = A::Error,
183+
InitError = A::InitError,
184+
>,
181185
{
182186
fn clone(&self) -> Self {
183187
Self {
184-
a: self.a.clone(),
185-
b: self.b.clone(),
188+
inner: self.inner.clone(),
186189
}
187190
}
188191
}
189192

190193
#[pin_project::pin_project]
191-
pub struct AndThenServiceFactoryResponse<A, B>
194+
pub(crate) struct AndThenServiceFactoryResponse<A, B>
192195
where
193196
A: ServiceFactory,
194197
B: ServiceFactory<Request = A::Response>,

actix-service/src/and_then_apply_fn.rs

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
use std::future::Future;
22
use std::marker::PhantomData;
33
use std::pin::Pin;
4+
use std::rc::Rc;
45
use std::task::{Context, Poll};
56

67
use crate::cell::Cell;
78
use crate::{Service, ServiceFactory};
89

910
/// `Apply` service combinator
10-
pub struct AndThenApplyFn<A, B, F, Fut, Res, Err>
11+
pub(crate) struct AndThenApplyFn<A, B, F, Fut, Res, Err>
1112
where
1213
A: Service,
1314
B: Service,
1415
F: FnMut(A::Response, &mut B) -> Fut,
1516
Fut: Future<Output = Result<Res, Err>>,
1617
Err: From<A::Error> + From<B::Error>,
1718
{
18-
a: A,
19-
b: Cell<(B, F)>,
19+
srv: Cell<(A, B, F)>,
2020
r: PhantomData<(Fut, Res, Err)>,
2121
}
2222

@@ -31,25 +31,23 @@ where
3131
/// Create new `Apply` combinator
3232
pub(crate) fn new(a: A, b: B, f: F) -> Self {
3333
Self {
34-
a,
35-
b: Cell::new((b, f)),
34+
srv: Cell::new((a, b, f)),
3635
r: PhantomData,
3736
}
3837
}
3938
}
4039

4140
impl<A, B, F, Fut, Res, Err> Clone for AndThenApplyFn<A, B, F, Fut, Res, Err>
4241
where
43-
A: Service + Clone,
42+
A: Service,
4443
B: Service,
4544
F: FnMut(A::Response, &mut B) -> Fut,
4645
Fut: Future<Output = Result<Res, Err>>,
4746
Err: From<A::Error> + From<B::Error>,
4847
{
4948
fn clone(&self) -> Self {
5049
AndThenApplyFn {
51-
a: self.a.clone(),
52-
b: self.b.clone(),
50+
srv: self.srv.clone(),
5351
r: PhantomData,
5452
}
5553
}
@@ -69,23 +67,25 @@ where
6967
type Future = AndThenApplyFnFuture<A, B, F, Fut, Res, Err>;
7068

7169
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
72-
let not_ready = self.a.poll_ready(cx)?.is_pending();
73-
if self.b.get_mut().0.poll_ready(cx)?.is_pending() || not_ready {
70+
let inner = self.srv.get_mut();
71+
let not_ready = inner.0.poll_ready(cx)?.is_pending();
72+
if inner.1.poll_ready(cx)?.is_pending() || not_ready {
7473
Poll::Pending
7574
} else {
7675
Poll::Ready(Ok(()))
7776
}
7877
}
7978

8079
fn call(&mut self, req: A::Request) -> Self::Future {
80+
let fut = self.srv.get_mut().0.call(req);
8181
AndThenApplyFnFuture {
82-
state: State::A(self.a.call(req), Some(self.b.clone())),
82+
state: State::A(fut, Some(self.srv.clone())),
8383
}
8484
}
8585
}
8686

8787
#[pin_project::pin_project]
88-
pub struct AndThenApplyFnFuture<A, B, F, Fut, Res, Err>
88+
pub(crate) struct AndThenApplyFnFuture<A, B, F, Fut, Res, Err>
8989
where
9090
A: Service,
9191
B: Service,
@@ -108,7 +108,7 @@ where
108108
Err: From<A::Error>,
109109
Err: From<B::Error>,
110110
{
111-
A(#[pin] A::Future, Option<Cell<(B, F)>>),
111+
A(#[pin] A::Future, Option<Cell<(A, B, F)>>),
112112
B(#[pin] Fut),
113113
Empty,
114114
}
@@ -134,7 +134,7 @@ where
134134
let mut b = b.take().unwrap();
135135
this.state.set(State::Empty);
136136
let b = b.get_mut();
137-
let fut = (&mut b.1)(res, &mut b.0);
137+
let fut = (&mut b.2)(res, &mut b.1);
138138
this.state.set(State::B(fut));
139139
self.poll(cx)
140140
}
@@ -150,10 +150,8 @@ where
150150
}
151151

152152
/// `AndThenApplyFn` service factory
153-
pub struct AndThenApplyFnFactory<A, B, F, Fut, Res, Err> {
154-
a: A,
155-
b: B,
156-
f: F,
153+
pub(crate) struct AndThenApplyFnFactory<A, B, F, Fut, Res, Err> {
154+
srv: Rc<(A, B, F)>,
157155
r: PhantomData<(Fut, Res, Err)>,
158156
}
159157

@@ -168,25 +166,16 @@ where
168166
/// Create new `ApplyNewService` new service instance
169167
pub(crate) fn new(a: A, b: B, f: F) -> Self {
170168
Self {
171-
a: a,
172-
b: b,
173-
f: f,
169+
srv: Rc::new((a, b, f)),
174170
r: PhantomData,
175171
}
176172
}
177173
}
178174

179-
impl<A, B, F, Fut, Res, Err> Clone for AndThenApplyFnFactory<A, B, F, Fut, Res, Err>
180-
where
181-
A: Clone,
182-
B: Clone,
183-
F: Clone,
184-
{
175+
impl<A, B, F, Fut, Res, Err> Clone for AndThenApplyFnFactory<A, B, F, Fut, Res, Err> {
185176
fn clone(&self) -> Self {
186177
Self {
187-
a: self.a.clone(),
188-
b: self.b.clone(),
189-
f: self.f.clone(),
178+
srv: self.srv.clone(),
190179
r: PhantomData,
191180
}
192181
}
@@ -210,18 +199,19 @@ where
210199
type Future = AndThenApplyFnFactoryResponse<A, B, F, Fut, Res, Err>;
211200

212201
fn new_service(&self, cfg: A::Config) -> Self::Future {
202+
let srv = &*self.srv;
213203
AndThenApplyFnFactoryResponse {
214204
a: None,
215205
b: None,
216-
f: self.f.clone(),
217-
fut_a: self.a.new_service(cfg.clone()),
218-
fut_b: self.b.new_service(cfg),
206+
f: srv.2.clone(),
207+
fut_a: srv.0.new_service(cfg.clone()),
208+
fut_b: srv.1.new_service(cfg),
219209
}
220210
}
221211
}
222212

223213
#[pin_project::pin_project]
224-
pub struct AndThenApplyFnFactoryResponse<A, B, F, Fut, Res, Err>
214+
pub(crate) struct AndThenApplyFnFactoryResponse<A, B, F, Fut, Res, Err>
225215
where
226216
A: ServiceFactory,
227217
B: ServiceFactory<Config = A::Config, InitError = A::InitError>,
@@ -267,8 +257,11 @@ where
267257

268258
if this.a.is_some() && this.b.is_some() {
269259
Poll::Ready(Ok(AndThenApplyFn {
270-
a: this.a.take().unwrap(),
271-
b: Cell::new((this.b.take().unwrap(), this.f.clone())),
260+
srv: Cell::new((
261+
this.a.take().unwrap(),
262+
this.b.take().unwrap(),
263+
this.f.clone(),
264+
)),
272265
r: PhantomData,
273266
}))
274267
} else {

0 commit comments

Comments
 (0)