Index: /CKEditor/trunk/CHANGES.html
===================================================================
--- /CKEditor/trunk/CHANGES.html	(revision 4522)
+++ /CKEditor/trunk/CHANGES.html	(revision 4523)
@@ -70,4 +70,5 @@
 		<li><a href="http://dev.fckeditor.net/ticket/4041">#4041</a> : Fixed open context menu on multiple cells to remove them result in only one removed.</li>
 		<li><a href="http://dev.fckeditor.net/ticket/4185">#4185</a> : Fixed resize handler effect doesn't affect flash object on output.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4196">#4196</a> : Fixed 'Remove Numbered/Bulleted List' on nested list doesn't work well on nested list.</li>
 	<h3>
 		CKEditor 3.0.1</h3>
Index: /CKEditor/trunk/_source/core/htmlparser/element.js
===================================================================
--- /CKEditor/trunk/_source/core/htmlparser/element.js	(revision 4522)
+++ /CKEditor/trunk/_source/core/htmlparser/element.js	(revision 4523)
@@ -36,5 +36,5 @@
 
 	var dtd			= CKEDITOR.dtd,
-		isBlockLike	= !!( dtd.$block[ name ] || dtd.$listItem[ name ] || dtd.$tableContent[ name ] || dtd.$nonEditable[ name ] ),
+		isBlockLike	= !!( dtd.$block[ name ] || dtd.$listItem[ name ] || dtd.$tableContent[ name ] || dtd.$nonEditable[ name ] || name == 'br' ),
 		isEmpty		= !!dtd.$empty[ name ];
 
Index: /CKEditor/trunk/_source/plugins/list/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/list/plugin.js	(revision 4522)
+++ /CKEditor/trunk/_source/plugins/list/plugin.js	(revision 4523)
@@ -357,5 +357,4 @@
 		compensateBrs();
 
-		var rootParent = groupObj.root.getParent();
 		docFragment.replace( groupObj.root );
 	}
@@ -446,4 +445,6 @@
 				{
 					var path = new CKEDITOR.dom.elementPath( block ),
+						pathElements = path.elements,
+						pathElementsCount = pathElements.length,
 						listNode = null,
 						processedFlag = false,
@@ -452,8 +453,8 @@
 
 					// First, try to group by a list ancestor.
-					for ( var i = 0 ; i < path.elements.length &&
-						  ( element = path.elements[ i ] ) && !element.equals( blockLimit ); i++ )
-					{
-						if ( listNodeNames[ element.getName() ] )
+					for ( var i = pathElementsCount - 1; i >= 0 && ( element = pathElements[ i ] ); i-- )
+					{
+						if ( listNodeNames[ element.getName() ]
+							 && blockLimit.contains( element ) )     // Don't leak outside block limit (#3940).
 						{
 							// If we've encountered a list inside a block limit
