diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index 7244dd6ccbf4e15615a1cb2c4754d20702ee650b..f5d8cc8f349b26339d089cbc3e5dacd04cbb4314 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -718,4 +718,105 @@ CALL test.p1(13);
 Warnings:
 Warning	1196	Some non-transactional changed tables couldn't be rolled back
 drop table t1;
+create table t1 (f1 integer) partition by range(f1)
+(partition p1 values less than (0), partition p2 values less than (10));
+insert into t1 set f1 = null;
+select * from t1 where f1 is null;
+f1
+NULL
+explain partitions select * from t1 where f1 is null;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p1	system	NULL	NULL	NULL	NULL	1	
+drop table t1;
+create table t1 (f1 integer) partition by list(f1)
+(partition p1 values in (1), partition p2 values in (null));
+insert into t1 set f1 = null;
+insert into t1 set f1 = 1;
+select * from t1 where f1 is null or f1 = 1;
+f1
+1
+NULL
+drop table t1;
+create table t1 (f1 smallint)
+partition by list (f1) (partition p0 values in (null));
+insert into t1 values (null);
+select * from t1 where f1 is null;
+f1
+NULL
+drop table t1;
+create table t1 (f1 smallint)
+partition by range (f1) (partition p0 values less than (0));
+insert into t1 values (null);
+select * from t1 where f1 is null;
+f1
+NULL
+drop table t1;
+create table t1 (f1 integer) partition by list(f1)
+(
+partition p1 values in (1),
+partition p2 values in (NULL),
+partition p3 values in (2),
+partition p4 values in (3),
+partition p5 values in (4)
+);
+insert into t1 values (1),(2),(3),(4),(null);
+select * from t1 where f1 < 3;
+f1
+1
+2
+explain partitions select * from t1 where f1 < 3;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p1,p3	ALL	NULL	NULL	NULL	NULL	2	Using where
+select * from t1 where f1 is null;
+f1
+NULL
+explain partitions select * from t1 where f1 is null;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p2	system	NULL	NULL	NULL	NULL	1	
+drop table t1;
+create table t1 (f1 int) partition by list(f1 div 2)
+(
+partition p1 values in (1),
+partition p2 values in (NULL),
+partition p3 values in (2),
+partition p4 values in (3),
+partition p5 values in (4)
+);
+insert into t1 values (2),(4),(6),(8),(null);
+select * from t1 where f1 < 3;
+f1
+2
+explain partitions select * from t1 where f1 < 3;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p1,p2,p3,p4,p5	ALL	NULL	NULL	NULL	NULL	5	Using where
+select * from t1 where f1 is null;
+f1
+NULL
+explain partitions select * from t1 where f1 is null;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p2	system	NULL	NULL	NULL	NULL	1	
+drop table t1;
+create table t1 (a int) partition by LIST(a) (
+partition pn values in (NULL),
+partition p0 values in (0),
+partition p1 values in (1),
+partition p2 values in (2)
+);
+insert into t1 values (NULL),(0),(1),(2);
+select * from t1 where a is null or a < 2;
+a
+NULL
+0
+1
+explain partitions select * from t1 where a is null or a < 2;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	pn,p0,p1	ALL	NULL	NULL	NULL	NULL	3	Using where
+select * from t1 where a is null or a < 0 or a > 1;
+a
+NULL
+2
+explain partitions select * from t1 where a is null or a < 0 or a > 1;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	pn,p2	ALL	NULL	NULL	NULL	NULL	2	Using where
+drop table t1;
 End of 5.1 tests
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index ad01977a4589f0cd54ff1f52627ff2c33f1c67be..c3e32e832bfc6b6ee99a78c4cefcef72245f0663 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -849,4 +849,79 @@ CALL test.p1(12);
 CALL test.p1(13);
 drop table t1;
 
+#
+# Bug#18053 Partitions: crash if null
+# Bug#18070 Partitions: wrong result on WHERE ... IS NULL
+#
+create table t1 (f1 integer) partition by range(f1)
+(partition p1 values less than (0), partition p2 values less than (10));
+insert into t1 set f1 = null;
+select * from t1 where f1 is null;
+explain partitions select * from t1 where f1 is null;
+drop table t1;
+
+create table t1 (f1 integer) partition by list(f1)
+(partition p1 values in (1), partition p2 values in (null));
+insert into t1 set f1 = null;
+insert into t1 set f1 = 1;
+select * from t1 where f1 is null or f1 = 1;
+drop table t1;
+
+create table t1 (f1 smallint)
+partition by list (f1) (partition p0 values in (null));
+insert into t1 values (null);
+select * from t1 where f1 is null;
+drop table t1;
+
+create table t1 (f1 smallint)
+partition by range (f1) (partition p0 values less than (0));
+insert into t1 values (null);
+select * from t1 where f1 is null;
+drop table t1;
+
+create table t1 (f1 integer) partition by list(f1)
+(
+ partition p1 values in (1),
+ partition p2 values in (NULL),
+ partition p3 values in (2),
+ partition p4 values in (3),
+ partition p5 values in (4)
+);
+
+insert into t1 values (1),(2),(3),(4),(null);
+select * from t1 where f1 < 3;
+explain partitions select * from t1 where f1 < 3;
+select * from t1 where f1 is null;
+explain partitions select * from t1 where f1 is null;
+drop table t1;
+
+create table t1 (f1 int) partition by list(f1 div 2)
+(
+ partition p1 values in (1),
+ partition p2 values in (NULL),
+ partition p3 values in (2),
+ partition p4 values in (3),
+ partition p5 values in (4)
+);
+
+insert into t1 values (2),(4),(6),(8),(null);
+select * from t1 where f1 < 3;
+explain partitions select * from t1 where f1 < 3;
+select * from t1 where f1 is null;
+explain partitions select * from t1 where f1 is null;
+drop table t1;
+
+create table t1 (a int) partition by LIST(a) (
+  partition pn values in (NULL),
+  partition p0 values in (0),
+  partition p1 values in (1),
+  partition p2 values in (2)
+);
+insert into t1 values (NULL),(0),(1),(2);
+select * from t1 where a is null or a < 2;
+explain partitions select * from t1 where a is null or a < 2;
+select * from t1 where a is null or a < 0 or a > 1;
+explain partitions select * from t1 where a is null or a < 0 or a > 1;
+drop table t1;
+
 --echo End of 5.1 tests
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index e9ebd9cbccb72bc3d5c3fffcab8d790459557976..36de27ef3e3f3a29abea6c08da93a001efa2731b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2296,6 +2296,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
   RANGE_OPT_PARAM  *range_par= &prune_param.range_param;
 
   prune_param.part_info= part_info;
+  prune_param.part_iter.has_null_value= FALSE;
 
   init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
   range_par->mem_root= &alloc;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 682c74dc31e6a709dac912ac36f57261de495d5b..d8a886d222784a5af4001db0265b3da2bfef8937 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -2868,9 +2868,6 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
   /* Get the partitioning function value for the endpoint */
   longlong part_func_value= part_val_int(part_info->part_expr);
 
-  if (part_info->part_expr->null_value)
-    DBUG_RETURN(0);
-
   while (max_part_id > min_part_id)
   {
     loc_part_id= (max_part_id + min_part_id + 1) >> 1;
@@ -5745,6 +5742,19 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
   else
     DBUG_ASSERT(0);
 
+  if (field->real_maybe_null() && part_info->has_null_value)
+  {
+    if (*min_value)
+    {
+      if (*max_value && !(flags & (NO_MIN_RANGE | NO_MAX_RANGE)))
+      {
+        init_single_partition_iterator(part_info->has_null_part_id, part_iter);
+        return 1;
+      }
+      if (!(flags & NEAR_MIN))
+        part_iter->has_null_value= TRUE;
+    }
+  }
   /* Find minimum */
   if (flags & NO_MIN_RANGE)
     part_iter->part_nums.start= 0;
@@ -5956,7 +5966,14 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter)
 uint32 get_next_partition_id_list(PARTITION_ITERATOR *part_iter)
 {
   if (part_iter->part_nums.start == part_iter->part_nums.end)
+  {
+    if (part_iter->has_null_value)
+    {
+      part_iter->has_null_value= FALSE;
+      return part_iter->part_info->has_null_part_id;
+    }
     return NOT_A_PARTITION_ID;
+  }
   else
     return part_iter->part_info->list_array[part_iter->
                                             part_nums.start++].partition_id;
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index 4982b1fcf1f48acb8f2198ef54a005c91855eabd..c214be81ae40788e554391c317595e27a5442b12 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -124,7 +124,7 @@ typedef uint32 (*partition_iter_func)(st_partition_iter* part_iter);
 typedef struct st_partition_iter
 {
   partition_iter_func get_next;
-  
+  bool has_null_value;
   struct st_part_num_range
   {
     uint32 start;