diff mbox series

[_GLIBCXX_DEBUG] Improve valid_range check

Message ID 4c480186-d9eb-9749-88aa-6a9a6e5eec3e@gmail.com
State New
Headers show
Series [_GLIBCXX_DEBUG] Improve valid_range check | expand

Commit Message

François Dumont Nov. 22, 2019, 5:38 p.m. UTC
Hi

     I noticed that we are not checking that iterators are not singular 
in valid_range. Moreover __check_singular signature for pointers is not 
intercepting all kind of pointers in terms of qualification.

     I'd like to commit it next week but considering we are in stage 3 I 
need proper acceptance.

     * include/debug/functions.h: Remove <bits/move.h> include.
     (__check_singular_aux, __check_singular): Move...
     * include/debug/helper_functions.h:
     (__check_singular_aux, __check_singular): ...here.
     (__valid_range_aux): Adapt to use latter.
     * testsuite/25_algorithms/copy/debug/2_neg.cc: New.

Tested under Linux x86_64 normal and debug modes.

François

Comments

Jonathan Wakely Nov. 22, 2019, 5:59 p.m. UTC | #1
On 22/11/19 18:38 +0100, François Dumont wrote:
>Hi
>
>    I noticed that we are not checking that iterators are not singular 
>in valid_range. Moreover __check_singular signature for pointers is 
>not intercepting all kind of pointers in terms of qualification.
>
>    I'd like to commit it next week but considering we are in stage 3 
>I need proper acceptance.
>
>    * include/debug/functions.h: Remove <bits/move.h> include.
>    (__check_singular_aux, __check_singular): Move...
>    * include/debug/helper_functions.h:
>    (__check_singular_aux, __check_singular): ...here.
>    (__valid_range_aux): Adapt to use latter.
>    * testsuite/25_algorithms/copy/debug/2_neg.cc: New.
>
>Tested under Linux x86_64 normal and debug modes.

OK for trunk, thanks.
Stephan Bergmann Nov. 26, 2019, 11:33 a.m. UTC | #2
On 22/11/2019 18:59, Jonathan Wakely wrote:
> On 22/11/19 18:38 +0100, François Dumont wrote:
>>     I noticed that we are not checking that iterators are not singular 
>> in valid_range. Moreover __check_singular signature for pointers is 
>> not intercepting all kind of pointers in terms of qualification.
>>
>>     I'd like to commit it next week but considering we are in stage 3 
>> I need proper acceptance.
>>
>>     * include/debug/functions.h: Remove <bits/move.h> include.
>>     (__check_singular_aux, __check_singular): Move...
>>     * include/debug/helper_functions.h:
>>     (__check_singular_aux, __check_singular): ...here.
>>     (__valid_range_aux): Adapt to use latter.
>>     * testsuite/25_algorithms/copy/debug/2_neg.cc: New.
>>
>> Tested under Linux x86_64 normal and debug modes.
> 
> OK for trunk, thanks.

The curly braces...

> diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
> index c3e7478f649..5a858754875 100644
> --- a/libstdc++-v3/include/debug/helper_functions.h
> +++ b/libstdc++-v3/include/debug/helper_functions.h
[...]
> @@ -138,14 +156,23 @@ namespace __gnu_debug
>      inline bool
>      __valid_range_aux(_InputIterator __first, _InputIterator __last,
>  		      std::input_iterator_tag)
> -    { return true; }
> +    {
> +      if (__first != __last)
> +	return !__check_singular(__first) && !__check_singular(__last);
> +
> +      return true;
> +    }
>  
>    template<typename _InputIterator>
>      _GLIBCXX_CONSTEXPR
>      inline bool
>      __valid_range_aux(_InputIterator __first, _InputIterator __last,
>  		      std::random_access_iterator_tag)
> -    { return __first <= __last; }
> +    {
> +      return
> +	__valid_range_aux(__first, __last, std::input_iterator_tag{})

...^^^ here...

> +	&& __first <= __last;
> +    }
>  
>    /** We have iterators, so figure out what kind of iterators they are
>     *  to see if we can check the range ahead of time.
> @@ -167,6 +194,9 @@ namespace __gnu_debug
>  		      typename _Distance_traits<_InputIterator>::__type& __dist,
>  		      std::__false_type)
>      {
> +      if (!__valid_range_aux(__first, __last, std::input_iterator_tag{}))

...and ^^^ here are not allowed pre C++11.  Replacing those with

   std::input_iterator_tag()

should fix it.

> +	return false;
> +
>        __dist = __get_distance(__first, __last);
>        switch (__dist.second)
>  	{
Jonathan Wakely Nov. 26, 2019, 12:21 p.m. UTC | #3
On 26/11/19 12:33 +0100, Stephan Bergmann wrote:
>On 22/11/2019 18:59, Jonathan Wakely wrote:
>>On 22/11/19 18:38 +0100, François Dumont wrote:
>>>    I noticed that we are not checking that iterators are not 
>>>singular in valid_range. Moreover __check_singular signature for 
>>>pointers is not intercepting all kind of pointers in terms of 
>>>qualification.
>>>
>>>    I'd like to commit it next week but considering we are in 
>>>stage 3 I need proper acceptance.
>>>
>>>    * include/debug/functions.h: Remove <bits/move.h> include.
>>>    (__check_singular_aux, __check_singular): Move...
>>>    * include/debug/helper_functions.h:
>>>    (__check_singular_aux, __check_singular): ...here.
>>>    (__valid_range_aux): Adapt to use latter.
>>>    * testsuite/25_algorithms/copy/debug/2_neg.cc: New.
>>>
>>>Tested under Linux x86_64 normal and debug modes.
>>
>>OK for trunk, thanks.
>
>The curly braces...
>
>>diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
>>index c3e7478f649..5a858754875 100644
>>--- a/libstdc++-v3/include/debug/helper_functions.h
>>+++ b/libstdc++-v3/include/debug/helper_functions.h
>[...]
>>@@ -138,14 +156,23 @@ namespace __gnu_debug
>>     inline bool
>>     __valid_range_aux(_InputIterator __first, _InputIterator __last,
>> 		      std::input_iterator_tag)
>>-    { return true; }
>>+    {
>>+      if (__first != __last)
>>+	return !__check_singular(__first) && !__check_singular(__last);
>>+
>>+      return true;
>>+    }
>>   template<typename _InputIterator>
>>     _GLIBCXX_CONSTEXPR
>>     inline bool
>>     __valid_range_aux(_InputIterator __first, _InputIterator __last,
>> 		      std::random_access_iterator_tag)
>>-    { return __first <= __last; }
>>+    {
>>+      return
>>+	__valid_range_aux(__first, __last, std::input_iterator_tag{})
>
>...^^^ here...
>
>>+	&& __first <= __last;
>>+    }
>>   /** We have iterators, so figure out what kind of iterators they are
>>    *  to see if we can check the range ahead of time.
>>@@ -167,6 +194,9 @@ namespace __gnu_debug
>> 		      typename _Distance_traits<_InputIterator>::__type& __dist,
>> 		      std::__false_type)
>>     {
>>+      if (!__valid_range_aux(__first, __last, std::input_iterator_tag{}))
>
>...and ^^^ here are not allowed pre C++11.  Replacing those with
>
>  std::input_iterator_tag()
>
>should fix it.

Indeed. We should also have tests that use "-std=gnu++98
-D_GLIBCXX_DEBUG" so they'd catch this.

François, can you take care of the fix please?
François Dumont Nov. 26, 2019, 7:07 p.m. UTC | #4
On 11/26/19 1:21 PM, Jonathan Wakely wrote:
> On 26/11/19 12:33 +0100, Stephan Bergmann wrote:
>> On 22/11/2019 18:59, Jonathan Wakely wrote:
>>> On 22/11/19 18:38 +0100, François Dumont wrote:
>>>>     I noticed that we are not checking that iterators are not 
>>>> singular in valid_range. Moreover __check_singular signature for 
>>>> pointers is not intercepting all kind of pointers in terms of 
>>>> qualification.
>>>>
>>>>     I'd like to commit it next week but considering we are in stage 
>>>> 3 I need proper acceptance.
>>>>
>>>>     * include/debug/functions.h: Remove <bits/move.h> include.
>>>>     (__check_singular_aux, __check_singular): Move...
>>>>     * include/debug/helper_functions.h:
>>>>     (__check_singular_aux, __check_singular): ...here.
>>>>     (__valid_range_aux): Adapt to use latter.
>>>>     * testsuite/25_algorithms/copy/debug/2_neg.cc: New.
>>>>
>>>> Tested under Linux x86_64 normal and debug modes.
>>>
>>> OK for trunk, thanks.
>>
>> The curly braces...
>>
>>> diff --git a/libstdc++-v3/include/debug/helper_functions.h 
>>> b/libstdc++-v3/include/debug/helper_functions.h
>>> index c3e7478f649..5a858754875 100644
>>> --- a/libstdc++-v3/include/debug/helper_functions.h
>>> +++ b/libstdc++-v3/include/debug/helper_functions.h
>> [...]
>>> @@ -138,14 +156,23 @@ namespace __gnu_debug
>>>     inline bool
>>>     __valid_range_aux(_InputIterator __first, _InputIterator __last,
>>>               std::input_iterator_tag)
>>> -    { return true; }
>>> +    {
>>> +      if (__first != __last)
>>> +    return !__check_singular(__first) && !__check_singular(__last);
>>> +
>>> +      return true;
>>> +    }
>>>   template<typename _InputIterator>
>>>     _GLIBCXX_CONSTEXPR
>>>     inline bool
>>>     __valid_range_aux(_InputIterator __first, _InputIterator __last,
>>>               std::random_access_iterator_tag)
>>> -    { return __first <= __last; }
>>> +    {
>>> +      return
>>> +    __valid_range_aux(__first, __last, std::input_iterator_tag{})
>>
>> ...^^^ here...
>>
>>> +    && __first <= __last;
>>> +    }
>>>   /** We have iterators, so figure out what kind of iterators they are
>>>    *  to see if we can check the range ahead of time.
>>> @@ -167,6 +194,9 @@ namespace __gnu_debug
>>>               typename _Distance_traits<_InputIterator>::__type& 
>>> __dist,
>>>               std::__false_type)
>>>     {
>>> +      if (!__valid_range_aux(__first, __last, 
>>> std::input_iterator_tag{}))
>>
>> ...and ^^^ here are not allowed pre C++11.  Replacing those with
>>
>>  std::input_iterator_tag()
>>
>> should fix it.
>
> Indeed. We should also have tests that use "-std=gnu++98
> -D_GLIBCXX_DEBUG" so they'd catch this.
>
> François, can you take care of the fix please?
>
>
>
Sure, I am about to do so.

However I wasn't sure about this syntax before the commit so I had run 
the new 2_neg.cc with:

make CXXFLAGS=-std=c++98 check-debug

and it worked fine and still is !

I also try -std=gnu++98 and made sure that pch had been updated by 
re-building libstdc++ first. I just can't get the expected compilation 
error.

Maybe I need to rebuild the whole stuff to get an error...

Sorry
Stephan Bergmann Nov. 26, 2019, 8:49 p.m. UTC | #5
On 26/11/2019 20:07, François Dumont wrote:
> However I wasn't sure about this syntax before the commit so I had run 
> the new 2_neg.cc with:
> 
> make CXXFLAGS=-std=c++98 check-debug
> 
> and it worked fine and still is !
> 
> I also try -std=gnu++98 and made sure that pch had been updated by 
> re-building libstdc++ first. I just can't get the expected compilation 
> error.
> 
> Maybe I need to rebuild the whole stuff to get an error...

I saw the error with recent Clang and -std=gnu++98.  Recent GCC indeed 
seems to give at most a warning.
François Dumont Nov. 26, 2019, 9:06 p.m. UTC | #6
On 11/26/19 9:49 PM, Stephan Bergmann wrote:
> On 26/11/2019 20:07, François Dumont wrote:
>> However I wasn't sure about this syntax before the commit so I had 
>> run the new 2_neg.cc with:
>>
>> make CXXFLAGS=-std=c++98 check-debug
>>
>> and it worked fine and still is !
>>
>> I also try -std=gnu++98 and made sure that pch had been updated by 
>> re-building libstdc++ first. I just can't get the expected 
>> compilation error.
>>
>> Maybe I need to rebuild the whole stuff to get an error...
>
> I saw the error with recent Clang and -std=gnu++98.  Recent GCC indeed 
> seems to give at most a warning.
>
>
Ok, thanks for the feedback, gcc might be more permissive then.

Whatever I committed the fix an hour ago.
Jonathan Wakely Nov. 26, 2019, 9:52 p.m. UTC | #7
On 26/11/19 20:07 +0100, François Dumont wrote:
>On 11/26/19 1:21 PM, Jonathan Wakely wrote:
>>On 26/11/19 12:33 +0100, Stephan Bergmann wrote:
>>>On 22/11/2019 18:59, Jonathan Wakely wrote:
>>>>On 22/11/19 18:38 +0100, François Dumont wrote:
>>>>>    I noticed that we are not checking that iterators are not 
>>>>>singular in valid_range. Moreover __check_singular signature 
>>>>>for pointers is not intercepting all kind of pointers in terms 
>>>>>of qualification.
>>>>>
>>>>>    I'd like to commit it next week but considering we are in 
>>>>>stage 3 I need proper acceptance.
>>>>>
>>>>>    * include/debug/functions.h: Remove <bits/move.h> include.
>>>>>    (__check_singular_aux, __check_singular): Move...
>>>>>    * include/debug/helper_functions.h:
>>>>>    (__check_singular_aux, __check_singular): ...here.
>>>>>    (__valid_range_aux): Adapt to use latter.
>>>>>    * testsuite/25_algorithms/copy/debug/2_neg.cc: New.
>>>>>
>>>>>Tested under Linux x86_64 normal and debug modes.
>>>>
>>>>OK for trunk, thanks.
>>>
>>>The curly braces...
>>>
>>>>diff --git a/libstdc++-v3/include/debug/helper_functions.h 
>>>>b/libstdc++-v3/include/debug/helper_functions.h
>>>>index c3e7478f649..5a858754875 100644
>>>>--- a/libstdc++-v3/include/debug/helper_functions.h
>>>>+++ b/libstdc++-v3/include/debug/helper_functions.h
>>>[...]
>>>>@@ -138,14 +156,23 @@ namespace __gnu_debug
>>>>    inline bool
>>>>    __valid_range_aux(_InputIterator __first, _InputIterator __last,
>>>>              std::input_iterator_tag)
>>>>-    { return true; }
>>>>+    {
>>>>+      if (__first != __last)
>>>>+    return !__check_singular(__first) && !__check_singular(__last);
>>>>+
>>>>+      return true;
>>>>+    }
>>>>  template<typename _InputIterator>
>>>>    _GLIBCXX_CONSTEXPR
>>>>    inline bool
>>>>    __valid_range_aux(_InputIterator __first, _InputIterator __last,
>>>>              std::random_access_iterator_tag)
>>>>-    { return __first <= __last; }
>>>>+    {
>>>>+      return
>>>>+    __valid_range_aux(__first, __last, std::input_iterator_tag{})
>>>
>>>...^^^ here...
>>>
>>>>+    && __first <= __last;
>>>>+    }
>>>>  /** We have iterators, so figure out what kind of iterators they are
>>>>   *  to see if we can check the range ahead of time.
>>>>@@ -167,6 +194,9 @@ namespace __gnu_debug
>>>>              typename _Distance_traits<_InputIterator>::__type& 
>>>>__dist,
>>>>              std::__false_type)
>>>>    {
>>>>+      if (!__valid_range_aux(__first, __last, 
>>>>std::input_iterator_tag{}))
>>>
>>>...and ^^^ here are not allowed pre C++11.  Replacing those with
>>>
>>> std::input_iterator_tag()
>>>
>>>should fix it.
>>
>>Indeed. We should also have tests that use "-std=gnu++98
>>-D_GLIBCXX_DEBUG" so they'd catch this.
>>
>>François, can you take care of the fix please?
>>
>>
>>
>Sure, I am about to do so.
>
>However I wasn't sure about this syntax before the commit so I had run 
>the new 2_neg.cc with:
>
>make CXXFLAGS=-std=c++98 check-debug
>
>and it worked fine and still is !

The testsuite doesn't use CXXFLAGS.


>I also try -std=gnu++98 and made sure that pch had been updated by 
>re-building libstdc++ first. I just can't get the expected compilation 
>error.
>
>Maybe I need to rebuild the whole stuff to get an error...

No, you need to pass the right flags so they are used by the
testsuite. This will do it:

make -C testsuite/  check-debug debug_flags=unix/-D_GLIBCXX_DEBUG/-std=gnu++98/-Wsystem-headers

But since it only shows up with -Wsystem-headers, there's no point
trying to test for it.
François Dumont Nov. 27, 2019, 5:37 a.m. UTC | #8
On 11/26/19 10:52 PM, Jonathan Wakely wrote:
> On 26/11/19 20:07 +0100, François Dumont wrote:
>> Sure, I am about to do so.
>>
>> However I wasn't sure about this syntax before the commit so I had 
>> run the new 2_neg.cc with:
>>
>> make CXXFLAGS=-std=c++98 check-debug
>>
>> and it worked fine and still is !
>
> The testsuite doesn't use CXXFLAGS.
>
Did you mean CPPFLAGS ?

I do see the option added to the compiler call in libstdc++.log file. 
And I used it to build for instance pretty-printers tests in 
_GLIBCXX_DEBUG mode with success.

>
>> I also try -std=gnu++98 and made sure that pch had been updated by 
>> re-building libstdc++ first. I just can't get the expected 
>> compilation error.
>>
>> Maybe I need to rebuild the whole stuff to get an error...
>
> No, you need to pass the right flags so they are used by the
> testsuite. This will do it:
>
> make -C testsuite/  check-debug 
> debug_flags=unix/-D_GLIBCXX_DEBUG/-std=gnu++98/-Wsystem-headers
I'll have to keep your mail to remember it !
>
> But since it only shows up with -Wsystem-headers, there's no point
> trying to test for it.
>
>
Ok, makes sens.

Thanks
Jonathan Wakely Nov. 27, 2019, 11:19 a.m. UTC | #9
On 27/11/19 06:37 +0100, François Dumont wrote:
>On 11/26/19 10:52 PM, Jonathan Wakely wrote:
>>On 26/11/19 20:07 +0100, François Dumont wrote:
>>>Sure, I am about to do so.
>>>
>>>However I wasn't sure about this syntax before the commit so I had 
>>>run the new 2_neg.cc with:
>>>
>>>make CXXFLAGS=-std=c++98 check-debug
>>>
>>>and it worked fine and still is !
>>
>>The testsuite doesn't use CXXFLAGS.
>>
>Did you mean CPPFLAGS ?

No, I mean CXXFLAGS.

>I do see the option added to the compiler call in libstdc++.log file. 
>And I used it to build for instance pretty-printers tests in 
>_GLIBCXX_DEBUG mode with success.

Ah, it works if you run it *inside* the $target/libstdc++-v3/testsuite
directory. I usually run the tests from the parent directory.


>>
>>>I also try -std=gnu++98 and made sure that pch had been updated by 
>>>re-building libstdc++ first. I just can't get the expected 
>>>compilation error.
>>>
>>>Maybe I need to rebuild the whole stuff to get an error...
>>
>>No, you need to pass the right flags so they are used by the
>>testsuite. This will do it:
>>
>>make -C testsuite/  check-debug 
>>debug_flags=unix/-D_GLIBCXX_DEBUG/-std=gnu++98/-Wsystem-headers
>I'll have to keep your mail to remember it !

Just look in testsuite/Makefile to see what variables are used by the
check-debug target. That's what determines the flags used, not my
email! :-)

>>But since it only shows up with -Wsystem-headers, there's no point
>>trying to test for it.
>>
>>
>Ok, makes sens.
>
>Thanks
>
diff mbox series

Patch

diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h
index 8c385b87244..12df745b573 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -29,7 +29,6 @@ 
 #ifndef _GLIBCXX_DEBUG_FUNCTIONS_H
 #define _GLIBCXX_DEBUG_FUNCTIONS_H 1
 
-#include <bits/move.h>		// for __addressof
 #include <bits/stl_function.h>	// for less
 
 #if __cplusplus >= 201103L
@@ -49,23 +48,6 @@  namespace __gnu_debug
   template<typename _Sequence>
     struct _Is_contiguous_sequence : std::__false_type { };
 
-  // An arbitrary iterator pointer is not singular.
-  inline bool
-  __check_singular_aux(const void*) { return false; }
-
-  // We may have an iterator that derives from _Safe_iterator_base but isn't
-  // a _Safe_iterator.
-  template<typename _Iterator>
-    inline bool
-    __check_singular(const _Iterator& __x)
-    { return __check_singular_aux(std::__addressof(__x)); }
-
-  /** Non-NULL pointers are nonsingular. */
-  template<typename _Tp>
-    inline bool
-    __check_singular(const _Tp* __ptr)
-    { return __ptr == 0; }
-
   /* Checks that [first, last) is a valid range, and then returns
    * __first. This routine is useful when we can't use a separate
    * assertion statement because, e.g., we are in a constructor.
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index c3e7478f649..5a858754875 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -29,6 +29,7 @@ 
 #ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H
 #define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1
 
+#include <bits/move.h>				// for __addressof
 #include <bits/stl_iterator_base_types.h>	// for iterator_traits,
 						// categories and _Iter_base
 #include <bits/cpp_type_traits.h>		// for __is_integer
@@ -112,6 +113,23 @@  namespace __gnu_debug
     __get_distance(_Iterator __lhs, _Iterator __rhs)
     { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
 
+  // An arbitrary iterator pointer is not singular.
+  inline bool
+  __check_singular_aux(const void*) { return false; }
+
+  // We may have an iterator that derives from _Safe_iterator_base but isn't
+  // a _Safe_iterator.
+  template<typename _Iterator>
+    inline bool
+    __check_singular(_Iterator const& __x)
+    { return __check_singular_aux(std::__addressof(__x)); }
+
+  /** Non-NULL pointers are nonsingular. */
+  template<typename _Tp>
+    inline bool
+    __check_singular(_Tp* const& __ptr)
+    { return __ptr == 0; }
+
   /** We say that integral types for a valid range, and defer to other
    *  routines to realize what to do with integral types instead of
    *  iterators.
@@ -138,14 +156,23 @@  namespace __gnu_debug
     inline bool
     __valid_range_aux(_InputIterator __first, _InputIterator __last,
 		      std::input_iterator_tag)
-    { return true; }
+    {
+      if (__first != __last)
+	return !__check_singular(__first) && !__check_singular(__last);
+
+      return true;
+    }
 
   template<typename _InputIterator>
     _GLIBCXX_CONSTEXPR
     inline bool
     __valid_range_aux(_InputIterator __first, _InputIterator __last,
 		      std::random_access_iterator_tag)
-    { return __first <= __last; }
+    {
+      return
+	__valid_range_aux(__first, __last, std::input_iterator_tag{})
+	&& __first <= __last;
+    }
 
   /** We have iterators, so figure out what kind of iterators they are
    *  to see if we can check the range ahead of time.
@@ -167,6 +194,9 @@  namespace __gnu_debug
 		      typename _Distance_traits<_InputIterator>::__type& __dist,
 		      std::__false_type)
     {
+      if (!__valid_range_aux(__first, __last, std::input_iterator_tag{}))
+	return false;
+
       __dist = __get_distance(__first, __last);
       switch (__dist.second)
 	{
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/debug/2_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy/debug/2_neg.cc
new file mode 100644
index 00000000000..8bbf873de96
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/debug/2_neg.cc
@@ -0,0 +1,37 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.2.1 [lib.alg.copy] Copy.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+void
+test01()
+{
+  int arr[] = { 0, 1, 2, 3, 4 };
+  std::copy((int*)0, arr + 5, arr);
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}